LOJ#6285. 数列分块入门 9
有点难.....
要求区间众数,所以我可以先把区间分块,然后我预处理出从第 i 块到第 j 块的众数,用dp[i][j]记录下来。
因为需要知道众数的num值, 所以我可以用一个vector来保存每个数的所有的出现位置,然后我待会我查询的时候就查询我所需要的[l, r]中有多少个这个数。
所以要求区间众数的时候,我可以通过之前打表的dp找出这中间完整的块的众数,然后对于边上的不完整的块,直接暴力扫过去,然后找最大的就可以了
#include<map> #include<set> #include<ctime> #include<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define first fi #define second se #define lowbit(x) (x & (-x)) typedef unsigned long long int ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 100000; const int maxm = 400; const int mod = 10007; using namespace std; int n, m, tol, T; int block; int a[maxn]; int b[maxn]; int cnt[maxn]; int belong[maxn]; int dp[maxm][maxm]; vector<int> v[maxn]; void init() { } int L(int x) { return (x-1) * block + 1; } int R(int x) { return min(n, x*block); } void handle(int x) { int ans = 0; int num = 0; memset(cnt, 0, sizeof cnt); for(int i=L(x); i<=n; i++) { cnt[a[i]]++; if(cnt[a[i]] > ans) { num = a[i]; ans = cnt[a[i]]; } if(cnt[a[i]] == ans && a[i] < num) { num = a[i]; ans = cnt[a[i]]; } dp[x][belong[i]] = num; } } int solve(int l, int r, int x) { return upper_bound(v[x].begin(), v[x].end(), r) - lower_bound(v[x].begin(), v[x].end(), l); } int query(int l, int r) { int num = dp[belong[l]+1][belong[r]-1]; int ans = solve(l, r, num); for(int i=l; i<=min(r, R(belong[l])); i++) { int t = solve(l, r, a[i]); if(t > ans) { ans = t; num = a[i]; } if(t == ans && a[i] < num) { ans = t; num = a[i]; } } if(belong[l] == belong[r]) return num; for(int i=L(belong[r]); i<=r; i++) { int t = solve(l, r, a[i]); if(t > ans) { ans = t; num = a[i]; } if(t == ans && a[i] < num) { ans = t; num = a[i]; } } return num; } int main() { while(~scanf("%d", &n)) { block = sqrt(n); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); belong[i] = (i-1) / block + 1; b[i] = a[i]; } sort(b+1, b+1+n); int nn = unique(b+1, b+1+n) - (b+1); for(int i=1; i<=n; i++) { a[i] = lower_bound(b+1, b+1+nn, a[i]) - b; v[a[i]].push_back(i); } for(int i=1; i<=belong[n]; i++) handle(i); m = n; while(m--) { int l, r; scanf("%d%d", &l, &r); int ans = query(l, r); printf("%d\n", b[ans]); } } return 0; }