P4168 [Violet] 蒲公英

查询区间众数。
先分块然后双指针把每两个块之间的答案算出来。
然后对于每个数在块间的出现次数做一个前缀和方便计算散块的答案。
整块直接得到答案。
散快用前缀和来计算即可。

点击查看代码
#include<bits/stdc++.h>
#define fir first
#define sec second
#define ll long long
#define pii pair<int,int>
#define e_b emplace_back 
#define p_b push_back
#define il inline
#define ios ios::sync_with_stdio(0),cin.tie(0)
using namespace std;
const int N=4e4+1,B=300;
int n,m;
int a[N],app[N][B],num[B][B],cnt[B][B];
int b[N],bsz,bl[B],br[B],tot;
int ans,t[N],len,vis[N];
signed main(){
    ios;cin>>n>>m,bsz=sqrt(n);
    for(int i=1;i<=n;i++){cin>>a[i];t[i]=a[i];}
    sort(t+1,t+n+1);len=unique(t+1,t+n+1)-t-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(t+1,t+len+1,a[i])-t;
    for(int k=1;(k-1)*bsz+1<=n;k++){
        for(int i=1;i<=len;i++)app[i][k]=app[i][k-1];
        tot=k;
        bl[k]=(k-1)*bsz+1,br[k]=min(k*bsz,n);
        for(int i=bl[k];i<=br[k];i++)app[a[i]][k]++,b[i]=k;
    }
    for(int l=1;l<=tot;l++){
        for(int i=1;i<=len;i++)vis[i]=0;
        int mx=0;
        for(int r=l;r<=tot;r++){
            for(int i=bl[r];i<=br[r];i++){
                vis[a[i]]++;
                if(vis[a[i]]>vis[mx])mx=a[i];
                if(vis[a[i]]==vis[mx]&&a[i]<mx)mx=a[i];
            }
            num[l][r]=mx,cnt[l][r]=vis[mx];
        }
    }
    //for(int l=1;l<=tot;l++)for(int r=l;r<=tot;r++)cout<<l<<' '<<r<<' '<<num[l][r]<<' '<<cnt[l][r]<<'\n';
    memset(vis,0,sizeof vis);
    while(m--){
        int l,r,kt;
        cin>>l>>r;
        l=((l+ans-1)%n)+1,r=((r+ans-1)%n)+1;
        if(l>r)swap(l,r);
        //cout<<ans<<' '<<l<<' '<<r<<'\n';
        if(b[r]==b[l]){
            ans=0;
            for(int i=l;i<=r;i++){
                vis[a[i]]++;
                if(vis[a[i]]>vis[ans])ans=a[i];
                if(vis[a[i]]==vis[ans]&&a[i]<ans)ans=a[i];
            }
            cout<<t[ans]<<'\n';
            ans=t[ans];
            for(int i=l;i<=r;i++)vis[a[i]]--;
            continue;
        }
        ans=num[b[l]+1][b[r]-1],kt=cnt[b[l]+1][b[r]-1];
        //cout<<ans<<' '<<kt<<'\n';
        vector<int>c;
        for(int i=l;i<=br[b[l]];i++){
            if(!vis[a[i]])c.e_b(a[i]);
            vis[a[i]]++;
        }
        for(int i=bl[b[r]];i<=r;i++){
            if(!vis[a[i]])c.e_b(a[i]);
            vis[a[i]]++;
        }
        for(int x:c){
            int t_app=app[x][b[r]-1]-app[x][b[l]];
            if(t_app+vis[x]>kt)ans=x,kt=t_app+vis[x];
            if(t_app+vis[x]==kt&&x<ans)ans=x,kt=t_app+vis[x];
        }
        cout<<t[ans]<<'\n';
        ans=t[ans];
        for(int i=l;i<=br[b[l]];i++)vis[a[i]]--;
        for(int i=bl[b[r]];i<=r;i++)vis[a[i]]--;
        
    }

    return 0;
}
posted @ 2025-10-10 15:11  zhuoheng  阅读(3)  评论(0)    收藏  举报