bzoj2724 [Violet 6]蒲公英
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2724
【题解】
比较经典的区间求众数问题。
我们考虑分块,ans[i,j]表示第i个块到第j个块答案是多少,这个可以预处理。
然后离散值,对于每个值存一个vector,里面存的是出现这个值的所有下标。
可以证明,答案只会在整块的答案和两端部分的所有数中选择,那么提取这些数,排序。
可以在vector中二分出出现的位置。就能求有多少个了,然后比较即可。
复杂度O(n根号nlogn)
# include <vector> # include <stdio.h> # include <string.h> # include <algorithm> // # include <bits/stdc++.h> using namespace std; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const int M = 4e4 + 10, N = 310, BLOCK = 200; const int mod = 1e9+7; # define RG register # define ST static int n, m, a[M], bl[M], B, q; int ans[N][N]; int bst[N], bnd[N]; vector<int> ps, tt, g[M]; int t[M], mx, mxid, lst; inline void prepare(int x) { int tem = x; mx = 0; mxid = 2333333; for (int i=(x-1)*BLOCK+1; i<=n; ++i) { t[a[i]] ++; if(t[a[i]] > mx) { mx = t[a[i]]; mxid = a[i]; } else if(t[a[i]] == mx) { if(a[i] < mxid) mxid = a[i]; } if(i == bnd[tem]) { ans[x][tem] = mxid; ++tem; } } for (int i=(x-1)*BLOCK+1; i<=n; ++i) --t[a[i]]; } int main() { scanf("%d%d", &n, &q); for (int i=1; i<=n; ++i) { scanf("%d", &a[i]); ps.push_back(a[i]); } sort(ps.begin(), ps.end()); ps.erase(unique(ps.begin(), ps.end()), ps.end()); for (int i=1; i<=n; ++i) { a[i] = lower_bound(ps.begin(), ps.end(), a[i]) - ps.begin() + 1; // printf("%d ", a[i]); g[a[i]].push_back(i); } // puts("\n================"); m = ps.size(); // for (int i=1; i<=m; ++i) { // printf("==size = %d\n", g[i].size()); // for (int j=0; j<g[i].size(); ++j) printf("%d ", g[i][j]); // puts(""); // } for (int i=1; i<=n; ++i) bl[i] = (i-1)/BLOCK+1; B = bl[n]; for (int i=1; i<=B; ++i) bst[i] = (i-1)*BLOCK+1, bnd[i] = min(n, i*BLOCK); for (int i=1; i<=B; ++i) prepare(i); lst = 0; while(q--) { int l, r; scanf("%d%d", &l, &r); l = (l+lst-1+n)%n+1; r = (r+lst-1+n)%n+1; if(l > r) swap(l, r); if(bl[l] == bl[r]) { mx = 0, mxid = 2333333; for (int i=l; i<=r; ++i) { t[a[i]] ++; if(t[a[i]] > mx) { mx = t[a[i]]; mxid = a[i]; } else if(t[a[i]] == mx) { if(a[i] < mxid) mxid = a[i]; } } for (int i=l; i<=r; ++i) --t[a[i]]; printf("%d\n", lst = ps[mxid-1]); } else { tt.clear(); if(bl[l] + 1 != bl[r]) tt.push_back(ans[bl[l]+1][bl[r]-1]); for (int i=l; i<=bnd[bl[l]]; ++i) tt.push_back(a[i]); for (int i=bst[bl[r]]; i<=r; ++i) tt.push_back(a[i]); sort(tt.begin(), tt.end()); tt.erase(unique(tt.begin(), tt.end()), tt.end()); // for (int i=0, sz=tt.size(); i<sz; ++i) printf("%d ", tt[i]); // puts("\n======"); mx = 0, mxid = 2333333; for (int i=0, sz=tt.size(); i<sz; ++i) { int x = tt[i]; int xi = upper_bound(g[x].begin(), g[x].end(), r)-g[x].begin(), xj = lower_bound(g[x].begin(), g[x].end(), l)-g[x].begin()+1; // printf("l = %d, r = %d\n", xj, xi); int times = upper_bound(g[x].begin(), g[x].end(), r)-lower_bound(g[x].begin(), g[x].end(), l); // printf("x=%d, times=%d\n", tt[i], times); if(times > mx) mx = times, mxid = x; } printf("%d\n", lst = ps[mxid-1]); } } return 0; }