题解 P5682 【次大值【民间数据】】

TRZ_2007

2019-11-24 14:58:54

Solution

## Solution 给你一个长度为$n$的数组,求将所有的$a_i \text{ mod } a_j (i,j\le n)$去重后的第二大值。 这题可以分点拿份,先看70tps的解法: 开下一个数组$book$,存下每一个$a_i \text{ mod } a_j$,然后暴力求解。 70pts: ```cpp #include <bits/stdc++.h> #pragma GCC optimize(3) using namespace std; const int N = 2e5+9; const int Inf = 1e5+9; int a[N],n,Max,sum; bool book[Inf]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { book[a[i] % a[j]] = true; Max = max(Max,a[i] % a[j]); } } for(int i=Max;i>=1;i--) { if(book[i] == true) sum++; if(sum == 2) { printf("%d\n",i); exit(0); } } if(sum < 2) { puts("-1"); exit(0); } } ``` 因为数组开不下$10^9$的内存,且$n \le 2 \times 10^5$的数据$\Theta(n^2)$的算法也会爆炸。 100pts解法: 其实较大的$a_i \text{ mod } a_j$必定是$a_i$,因为$a_i \text{ mod } a_j$必定小于$a_i$。所以这题就转换成了要你求$a$排序去重后的第二大值。 剩下来的就认识函数$unique$(去重函数)即可。 - 1:用法 $unique$的用法如下: ```cpp int k = unique(a+1,a+n+1) - a; ``` 解释:$k$表示数组$a$去重后还剩几个值,后面那一坨东西就把他当做$sort$的用法,最后加一个$ - a$ . - 2:复杂度 目测$\Theta(n\log n)$ 100pts代码: ```cpp #include <bits/stdc++.h> #pragma GCC optimize(3) using namespace std; const int N = 2e5+9; int a[N],n; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } sort(a+1,a+n+1); int k = unique(a+1,a+n+1) - a;//这行语句过后a早已被自动去重。 if(k <= 2) { puts("-1"); exit(0); } else { printf("%d\n",a[k - 3]); exit(0); } } ```