#分块#洛谷 4168 CH 4401 蒲公英

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/82050087

题目

求区间众数


分析

线段树和树状数组很难做的,分块可以做,离散后预处理,大段维护,小段朴素,就做完了


代码

#include <cstdio>
#include <cmath>
#include <algorithm>
#define cct(i,a,b) for (register int i=a;i<=b;i++)
int n,m,pos[40001],t[40001],a[40001],b[40001],st[201],ed[201],ans[201][201],sum[40001][201];
int in(){
    int ans=0; char c=getchar();
    while (c<48||c>57) c=getchar();
    while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
    return ans;
}
int answ(int l,int r){
    int p=pos[l],q=pos[r];
    if (p==q){//小段朴素
        int now=0;
        cct(i,l,r){
            t[a[i]]++;
            if (t[a[i]]>t[now]||t[a[i]]==t[now]&&now>a[i]) now=a[i];//求众数
        }
        cct(i,l,r) t[a[i]]--;
        return b[now];
    }
    int now=ans[p+1][q-1];
    t[now]+=sum[now][q-1]-sum[now][p];
    cct(i,l,ed[p]){
        if (!t[a[i]]) t[a[i]]+=sum[a[i]][q-1]-sum[a[i]][p];//暂且先记录下来
        t[a[i]]++;
        if (t[a[i]]>t[now]||t[a[i]]==t[now]&&now>a[i]) now=a[i];//求众数
    }
    cct(i,st[q],r){
        if (!t[a[i]]) t[a[i]]+=sum[a[i]][q-1]-sum[a[i]][p];//the same
        t[a[i]]++;
        if (t[a[i]]>t[now]||t[a[i]]==t[now]&&now>a[i]) now=a[i];
    }
    cct(i,l,ed[p]) t[a[i]]=0;//清空
    cct(i,st[q],r) t[a[i]]=0;
    t[ans[p+1][q-1]]=0;
    return b[now];
}
int main(){
    n=in(); m=in(); int pws=sqrt(n); 
    cct(i,1,n){
        a[i]=b[i]=in();
        pos[i]=(i+pws-1)/pws; ed[pos[i]]=i;
        if (!st[pos[i]]) st[pos[i]]=i; //分块
    }
    std::sort(b+1,b+1+n);
    int k=std::unique(b+1,b+1+n)-(b+1);//去重
    cct(i,1,n) a[i]=std::lower_bound(b+1,b+1+k,a[i])-b;//离散
    cct(i,1,pos[n]){
        int now=0;
        cct(j,st[i],n){
            t[a[j]]++;//数字++
            if (t[a[j]]>t[now]||t[a[j]]==t[now]&&now>a[j]) now=a[j];//求众数
            ans[i][pos[j]]=now;//记录答案
        }
        cct(j,st[i],n) t[a[j]]--;
    }
    cct(i,1,n) sum[a[i]][pos[i]]++;
    cct(i,1,k) cct(j,1,pos[n]) sum[i][j]+=sum[i][j-1];//前缀和
    int last=0;
    while (m--){
        int x=in(); int y=in();
        x=(x+last-1)%n+1; y=(y+last-1)%n+1;
        if (x>y) x^=y,y^=x,x^=y;//按照题目模拟
        last=answ(x,y);
        printf("%d\n",last);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/82050087
今日推荐