AcWing249 蒲公英(分块)

一道经典的分块例题,因为我们通过观察可知,区间众数要不就是中间所有块上的答案,要不就是两边小块上出现过的值

因此我们可以分块处理,只要预处理块与块之间的答案即可,因为本题没有修改操作

另外这题比较卡常,块的大小要先算好,不过也有复杂度更低的算法

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<string>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
const int N=1e6+10;
const int mod=1e9+7;
vector<int> g[N];
int d[2001][2001];
int c[N],a[N];
int n,m;
int block;
int cnt[N];
void init(){
    int l,r;
    for(l=1;l<=n;l+=block){
        int res=0;
        memset(cnt,0,sizeof cnt);
        for(r=l;r<=n;r++){
            cnt[a[r]]++;
            if(cnt[a[r]]>cnt[res]||cnt[a[r]]==cnt[res]&&a[r]<res)
            res=a[r];
            if(r%block==0||r==n)
            d[(l-1)/block+1][(r-1)/block+1]=res;
        }
    }
}
int find(int l,int r,int x){
    return upper_bound(g[x].begin(),g[x].end(),r)-lower_bound(g[x].begin(),g[x].end(),l);
}
int query(int l, int r){
    int ans = 0;
    int B=block;
    int idl = (l-1)/B+1, idr = (r-1)/B+1;
    if(idl+1 < idr) ans = d[idl+1][idr-1];
    int n = find(l,r,ans), n1;
    if(idl==idr){
        for(int i=l;i<=r;i++){
            n1 = find(l,r,a[i]);
            if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;
        }
    }
    else{
        for(int i=l;i<=idl*B;i++){
            n1 = find(l,r,a[i]);
            if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;
        }
        for(int i=(idr-1)*B+1;i<=r;i++){
            n1 = find(l,r,a[i]);
            if(n < n1 || n == n1 && a[i] < ans) ans = a[i], n = n1;
        }
    }
    return c[ans];
}

int main(){
    cin>>n>>m;
    int i;
    block=max(1,(int)(n/sqrt(m*log2(n))));
    for(i=1;i<=n;i++){
        scanf("%d",&a[i]);
        c[i]=a[i];
    }
    sort(c+1,c+1+n);
    for(i=1;i<=n;i++){
        a[i]=lower_bound(c+1,c+1+n,a[i])-c;
        g[a[i]].push_back(i);
    }
    init();
    int last=0;
    int l,r;
    while(m--){
        scanf("%d%d",&l,&r);
        l = (l+last-1)%n + 1;
        r = (r+last-1)%n + 1;
        if(l>r)
            swap(l,r);
        last=query(l,r);
        printf("%d
",last);
    }
}
View Code
原文地址:https://www.cnblogs.com/ctyakwf/p/12765131.html