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;
}

猜你喜欢

转载自www.cnblogs.com/captain1/p/9841073.html