【题解】[Violet]蒲公英

[Violet]蒲公英

\(\text{Solution:}\)

简单分块。由于信息不具有区间可减性一类的东西,线段树一类就不好维护了,考虑用分块来维护。

首先将值离散化,然后考虑预处理:\(p[i][j]\) 表示前 \(i\) 个块中 \(j\) 的出现次数, \(s[i][j]\) 表示块 \(i,j\) 之间的最小众数。

那么当询问两个区间的时候,涉及到的答案候选就只有左右散块的部分以及中间连续段的最小众数了。

\(p[i][j]\) 可以 \(O(n\sqrt{n})\) 预处理出来, \(s[i][j]\) 考虑枚举 \(i,j\) 块并暴力更新块内元素 可以 \(O(n\sqrt{n})\) 预处理。

考虑如何处理询问,当两块之间的间隔小于一个块的时候,暴力就可以做到 \(O(\sqrt{n})\) 级别复杂度了。

否则考虑暴力处理两端散块,用 \(p\) 数组获得中间连续段的数字出现次数,加上散块的来更新答案即可。

代码中不知道是不是有一些边界问题,改了一下块长就过了。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+10;
int B,bk[N],lastans;
int p[500][N],b[N],blen,bcnt,s[500][500];
int n,m,a[N],num,cnt[N],vis[N];
inline int Min(int x,int y){return x<y?x:y;}
inline int Max(int x,int y){return x>y?x:y;}
inline int getpos(int x){return lower_bound(b+1,b+blen+1,x)-b;}
vector<int>use;
int query(int l,int r){
    int L=bk[l];
    int R=bk[r];
    use.clear();
    if(R-L<=1){
        for(int i=l;i<=r;++i){
            if(!vis[a[i]])use.push_back(a[i]);
            vis[a[i]]++;
        }
        int pos=-1,ct=-1;
        for(auto i:use){
            if(vis[i]>ct){
                ct=vis[i];
                pos=i;
            }
            else if(vis[i]==ct&&i<pos)pos=i;
            vis[i]=0;
        }
        return pos;
    }
    int pos=s[bk[l]+1][bk[r]-1];
    int ct=p[bk[r]-1][pos]-p[bk[l]][pos];
    for(int i=l;i<=Min(bk[l]*B,n);++i){
        if(!vis[a[i]])use.push_back(a[i]);
        vis[a[i]]++;
    }
    for(int i=(bk[r]-1)*B+1;i<=r;++i){
        if(!vis[a[i]])use.push_back(a[i]);
        vis[a[i]]++;
    }
    for(auto i:use){
        if(vis[i]+p[bk[r]-1][i]-p[bk[l]][i]>ct){
            ct=vis[i]+p[bk[r]-1][i]-p[bk[l]][i];
            pos=i;
        }
        else if(vis[i]+p[bk[r]-1][i]-p[bk[l]][i]==ct&&i<pos)pos=i;
        vis[i]=0;
    }
    return pos;
}
void File(){
    freopen("in.txt","r",stdin);
    freopen("My.out","w",stdout);
}
signed main(){
    // File();
    scanf("%lld%lld",&n,&m);B=sqrt(n)+100;
    for(int i=1;i<=n;++i)scanf("%lld",&a[i]),b[++bcnt]=a[i];
    sort(b+1,b+bcnt+1);
    blen=unique(b+1,b+bcnt+1)-b-1;
    for(int i=1;i<=n;++i)a[i]=getpos(a[i]);
    for(int i=1;i<=n;++i){
        bk[i]=(i-1)/B+1;
        p[bk[i]][a[i]]++;
    }
    num=(n-1)/B+1;
    for(int i=1;i<=B;++i)
        for(int j=1;j<=blen;++j)
            p[i][j]+=p[i-1][j];
    for(int i=1;i<=num;++i){
        for(int j=1;j<=blen;++j)cnt[j]=0;
        int col=-1,ct=0;
        for(int j=i;j<=num;++j){
            for(int k=(j-1)*B+1;k<=Min(n,j*B);++k){
                cnt[a[k]]++;
                if(cnt[a[k]]>ct){
                    ct=cnt[a[k]];
                    col=a[k];
                }
                else if(cnt[a[k]]==ct&&a[k]<col)col=a[k];
            }
            s[i][j]=col;
        }
    }
    while(m--){
        int l,r;
        scanf("%lld%lld",&l,&r);
        l=(l+lastans-1)%n+1;
        r=(r+lastans-1)%n+1;
        if(l>r)swap(l,r);
        // printf("[%lld %lld]\n",l,r);
        // for(int i=l;i<=r;++i)printf("%lld ",b[a[i]]);
        // puts("");
        lastans=b[query(l,r)];
        printf("%lld\n",lastans);
    }
    return 0;
}
posted @ 2021-08-18 20:12  Refined_heart  阅读(53)  评论(0编辑  收藏  举报