Violet蒲公英
题目要求求出给定区间内编号最小的众数,强制在线。
虽然说这是个黑题……不过我们可以用暴力分块解决它。首先先对所有数离散化,这个不影响众数。我们先预处理出每个数在前i个块内出现了多少次,再预处理出块i到块j内最小众数是谁。前者很好预处理,后者的话,我们只要固定i,之后向后枚举,每次新加入一个数的时候就比较出现最多次的元素来更新当前众数。如果到了块末尾,就更新块的答案。
查询的时候,整块的我们直接去计算过的答案,之后对于每一个出现在零散位置的元素,我们记录下来,之后计算他们在整块中出现了多少次(前缀和相减即可),这样比较出出现次数最多的元素就可以。
这题的处理稍微有点复杂,我的做法是开个栈来记录当前出现在零散位置的元素。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 40005; const int N = 205; const int INF = 1000000009; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } int n,m,B,a[M],l[N],r[N],sum[M][N],ans[N][N],x,y,last,b[M],cnt,blo[M],tot,g = 1,cur[M],maxx; int sta[M],top,mpos; void init() { rep(i,1,cnt) { rep(j,1,n) sum[j][i] += sum[j][i-1]; rep(j,l[i],r[i]) sum[a[j]][i]++; } rep(i,1,cnt) { memset(cur,0,sizeof(cur)),maxx = mpos = 0,g = i; rep(j,l[i],n) { cur[a[j]]++; if(cur[a[j]] > maxx) maxx = cur[a[j]],mpos = a[j]; else if(cur[a[j]] == maxx && a[j] < mpos) mpos = a[j]; if(j == r[g]) ans[i][g] = mpos,g++; } } } int query(int x,int y) { memset(cur,0,sizeof(cur)),maxx = mpos = 0; int L = blo[x],R = blo[y]; if(L == R) { rep(i,x,y) { cur[a[i]]++; if(cur[a[i]] > maxx) maxx = cur[a[i]],mpos = a[i]; else if(cur[a[i]] == maxx && a[i] < mpos) mpos = a[i]; } return mpos; } int p = ans[L+1][R-1],now = sum[p][R-1] - sum[p][L]; rep(i,x,r[L]) { if(!cur[a[i]]) sta[++top] = a[i]; cur[a[i]]++; } rep(i,l[R],y) { if(!cur[a[i]]) sta[++top] = a[i]; cur[a[i]]++; } mpos = p; while(top) { int k = sta[top],q = sum[k][R-1] - sum[k][L] + cur[k]; if(q > now) now = q,mpos = k; else if(q == now && k < mpos) mpos = k; top--; } return mpos; } int main() { n = read(),m = read(),B = sqrt(n); cnt = (n % B) ? n / B + 1 : n / B; rep(i,1,cnt) l[i] = r[i-1] + 1,r[i] = l[i] + B - 1; r[cnt] = n; rep(i,1,n) a[i] = b[i] = read(); sort(b+1,b+1+n),tot = unique(b+1,b+1+n) - b - 1; rep(i,1,n) a[i] = lower_bound(b+1,b+1+tot,a[i]) - b; //rep(i,1,n) printf("%d ",a[i]);enter; rep(i,1,n) { blo[i] = g; if(i == r[g]) g++; } init(); rep(i,1,m) { x = read(),y = read(); x = (x + last - 1) % n + 1,y = (y + last - 1) % n + 1; if(x > y) swap(x,y); last = b[query(x,y)]; printf("%d\n",last); } return 0; }
当你意识到,每个上一秒都成为永恒。