数列分块9

写一下分块,写的是洛谷的强制在线版本,写完之后感觉有一些实现上的细节处理可以整理一下。

首先简单说说分块怎么写。

我们还是按照 \(\sqrt n\) 的大小分块,然后进行预处理。我们定义 \(sum[i][j]\) 为前 i 个块中 j 出现了多少次,\(dp[i][j]\) 为块 i 和块 j 中的众数是哪一个。

我们根据分块的思想来想,每一个询问区间都可以看做中间的完整块和左右的零散元素。我们想询问众数的话哪些数有可能成为众数。显然只有中间整块部分的众数,以及左右部分的元素可能成为答案,证明自证(滑稽)

我们可以枚举左右零散部分的元素加到一个桶里面,每次加进去就看一下能否更新答案即可

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

#define B printf("!");
#define calc(x) sum[col[r]-1][x]-sum[col[l]][x]
using namespace std;

int read()
{
    int a = 0,x = 1;char ch = getchar();
    while(ch > '9' || ch < '0') {if(ch == '-') x = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9') {a = a*10 + ch-'0';ch = getchar();}
    return a*x;
}
const int N=4e4+1,M=2e2+7;
int n,m,b,col[N],que[N],a[N],pos[N];
int sum[M][N],t[N],dp[M][M],qwq = 999;

int query(int l,int r)
{
    if(col[r]-col[l] <= 1) {
        int maxn = 0;
        for(int i = l;i <= r;i ++) {
            t[a[i]] ++;
            if(t[a[i]] > t[maxn] || (t[a[i]] == t[maxn] && a[i] < maxn)) maxn = a[i];
        }
        for(int i = l;i <= r;i ++) t[a[i]] --;
        return maxn;
    }
    int maxn = dp[col[l]+1][col[r]-1];
    for(int i = l;col[i] == col[l];i ++) {
        t[a[i]] ++;
        if(t[a[i]]+calc(a[i]) > t[maxn]+calc(maxn) || (t[a[i]]+calc(a[i]) == t[maxn]+calc(maxn) && a[i] < maxn))
            maxn = a[i];
    }

    for(int i = r;col[i] == col[r];i --) {
        t[a[i]] ++;
        if(t[a[i]]+calc(a[i]) > t[maxn]+calc(maxn) || (t[a[i]]+calc(a[i]) == t[maxn]+calc(maxn) && a[i] < maxn))
            maxn = a[i];
    }
    for(int i = l;col[i] == col[l];i ++) t[a[i]] --;
    for(int i = r;col[i] == col[r];i --) t[a[i]] --;
    return maxn;
}

int main()
{
    freopen("in.in","r",stdin);
    freopen("out.out","w",stdout);
    n = read(),m = read();b = sqrt(n);
    for(int i = 1;i <= n;i ++) a[i] = que[i] = read();
    for(int i = 1;i <= n;i ++) col[i] = (i-1)/b+1;
    sort(que+1,que+1+n);int len = unique(que+1,que+1+n) - que - 1;
    for(int i = 1,tmp;i <= n;i ++) a[i] = lower_bound(que+1,que+1+len,tmp=a[i]) - que,pos[a[i]] = tmp;
    for(int i = 1;i <= n;i ++) for(int j = col[i];j <= col[n];j ++) sum[j][a[i]] ++;
    for(int i = 1,maxn=0;i <= col[n];i ++) {
        for(int j = b*(i-1)+1;j <= n;j ++) {
            t[a[j]] ++;
            if(t[a[j]] > t[maxn] || (t[a[j]] == t[maxn] && a[j] < maxn)) maxn = a[j];
            dp[i][col[j]] = maxn;
        }
        memset(t,0,sizeof(t));maxn = 0;
    }

    for(int i = 1,x = 0;i <= m;i ++) {
            int l = read(),r = read();
            l = (l+x-1)%n+1,r = (r+x-1)%n+1;
            if(l > r) swap(l,r);
            printf("%d\n",x=pos[query(l,r)]);
    }
    return 0;
}
posted @ 2020-11-12 09:46  nao-nao  阅读(101)  评论(0编辑  收藏  举报