[BZOJ2724][Violet 6]蒲公英
2724: [Violet 6]蒲公英
Time Limit: 40 Sec Memory Limit: 512 MB Submit: 2404 Solved: 825 [Submit][Status][Discuss]Description
Input
修正一下
l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1
Output
Sample Input
6 3
1 2 3 2 1 2
1 5
3 6
1 5
1 2 3 2 1 2
1 5
3 6
1 5
Sample Output
1
2
1
2
1
HINT
修正下:
n <= 40000, m <= 50000
设$mode\left(A\right)$表示集合$A$的众数
那么有一个显然的定理为$mode\left(A\cup B\right)\in A\cup\left\{mode\left(B\right)\right\}$
需要离散化,时间复杂度$O\left(nlogn\right)$
分为$x$块
设$f[i][j]$为第i块到第j块的众数,通过枚举$i$来求,时间复杂度为$O\left(xn\right)$
对于每个询问$\left(l,r\right)$,把中间的整块里面的众数用$f$数组得到,然后边缘的暴力判断出现次数
而出现次数的求法为:对每个权值开一个vector记录出现位置,在里面二分
所以单次询问的复杂度为$O\left(\frac{nlogn}{x}\right)$
那么总时间复杂度为$O\left(nlogn\right)+O\left(xn\right)+O\left(\frac{mnlogn}{x}\right) \ge O\left(nlogn+n\sqrt{mlogn}\right)$
当且仅当$x=\sqrt{mlogn}$时等号成立
#include <bits/stdc++.h> using namespace std; inline int readint(){ int n = 0; char ch = getchar(); while(!isdigit(ch)) ch = getchar(); while(isdigit(ch)){ n = (n << 1) + (n << 3) + (ch ^ 48); ch = getchar(); } return n; } void output(int x){ if(x > 9) output(x / 10); putchar(x % 10 + 48); } const int maxn = 40000 + 10, blk = 300 + 10, siz = maxn / blk + 10, INF = 1 << 30; int n, m; int a[maxn]; int b[maxn], num[maxn], cnt; vector<int> vec[maxn]; int belong[maxn], le[blk], ri[blk]; int f[blk][blk], g[blk][blk]; inline int calc(int x, int l, int r){ return upper_bound(vec[x].begin(), vec[x].end(), r) - lower_bound(vec[x].begin(), vec[x].end(), l); } int main(){ n = readint(); m = readint(); for(int i = 1; i <= n; i++){ a[i] = b[i] = readint(); } sort(b + 1, b + n + 1); cnt = unique(b + 1, b + n + 1) - b; for(int i = 1; i < cnt; i++){ num[i] = b[i]; } for(int i = 1; i <= n; i++){ a[i] = lower_bound(b + 1, b + cnt, a[i]) - b; vec[a[i]].push_back(i); } for(int i = 1; (i - 1) * siz + 1 <= n; i++){ le[i] = (i - 1) * siz + 1; ri[i] = i * siz; if(ri[i] > n) ri[i] = n; for(int j = le[i]; j <= ri[i]; j++){ belong[j] = i; } } for(int i = 1; i <= belong[n]; i++){ f[i][i] = a[le[i]]; g[i][i] = calc(f[i][i], le[i], ri[i]); for(int s, k = le[i] + 1; k <= ri[i]; k++){ s = calc(a[k], le[i], ri[i]); if(s > g[i][i] || (s == g[i][i] && a[k] < f[i][i])){ f[i][i] = a[k]; g[i][i] = s; } } for(int j = i + 1; j <= belong[n]; j++){ f[i][j] = f[i][j - 1]; g[i][j] = calc(f[i][j], le[i], ri[j]); for(int s, k = le[j]; k <= ri[j]; k++){ s = calc(a[k], le[i], ri[j]); if(s > g[i][j] || (s == g[i][j] && a[k] < f[i][j])){ f[i][j] = a[k]; g[i][j] = s; } } } } int l, r, bl, br, last = 0, ans, t; while(m--){ l = (readint() + last - 1) % n + 1; r = (readint() + last - 1) % n + 1; if(l > r) swap(l, r); bl = belong[l]; br = belong[r]; ans = INF, t = 0; if(bl == br || bl + 1 == br){ for(int s, i = l; i <= r; i++){ s = calc(a[i], l, r); if(s > t || (s == t && a[i] < ans)){ ans = a[i]; t = s; } } } else{ for(int s, i = l; i <= ri[bl]; i++){ s = calc(a[i], l, r); if(s > t || (s == t && a[i] < ans)){ ans = a[i]; t = s; } } for(int s, i = le[br]; i <= r; i++){ s = calc(a[i], l, r); if(s > t || (s == t && a[i] < ans)){ ans = a[i]; t = s; } } int s = calc(f[bl + 1][br - 1], l, r); if(s > t || (s == t && f[bl + 1][br - 1] < ans)){ ans = f[bl + 1][br - 1]; t = s; } } output(last = num[ans]); puts(""); } return 0; }