bzoj2724[Violet 6]蒲公英

传送门

这个题是我晚自习的时候看到的,那个时候觉得这个题好简单啊,一上手才发现这个题好难写啊,调了好久都没调对
算法是分块!!
很显然众数不能直接合并,那么我们可以考虑每个块上记录这个块的众数。
对于每个询问,它可能包含多个块,由于众数不好合并,所以我们需要记录任意两个块之间的众数,这个直接循环预处理就好了
很显然,对于每个询问区间\([L,R]\),它的众数只可能是它包含的块的众数和多出来的那两段的数
如何统计那两段多出来的数在这个区间出现的次数?
考虑将每个数的位置存入vector中,每次二分查找就行了。
中间有个小插曲:一下子脑抽了,忘记了lower_bound是查询不小于的,看了篇博客说是不大于的,然后就一直wa,后来问了问别人才知道,改完就A了
记住离散化!
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<cstring>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=4e4+1;map<int,int>mp;
int n,m,a[maxn],id[maxn],mx,mxx,b[maxn],len,c[maxn],f[1001][1001],g[1001][1001],now,ans,num,w[maxn];
vector<int>d[maxn];
int main()
{
    read(n),read(m);len=sqrt(n*log(n));num=n/len+1;
    for(rg int i=1;i<=n;i++)read(a[i]),w[i]=a[i];
    sort(w+1,w+n+1);for(rg int i=1;i<=n;i++)if(!mp[w[i]])mp[w[i]]=++now;
    for(rg int i=1;i<=n;i++)c[i]=mp[a[i]];
    for(rg int i=1;i<=n;i++)mp[c[i]]=a[i];
    for(rg int i=1;i<=n;i++)id[i]=(i-1)/num+1;
    for(rg int i=1;i<=len;i++)
    {
        for(rg int j=(i-1)*num+1;j<=n;j++)
        {
            b[c[j]]++;
            if(b[c[j]]>mxx||(b[c[j]]==mxx&&mx>c[j]))mxx=b[c[j]],mx=c[j];
            f[i][id[j]]=mx,g[i][id[j]]=mxx;
        }
        memset(b,0,sizeof b),mx=mxx=0;
    }
    for(rg int i=1;i<=n;i++)d[c[i]].push_back(i);
    for(rg int i=1,x,y;i<=m;i++)
    {
        read(x),read(y);x=(x+ans-1)%n+1,y=(y+ans-1)%n+1;
        if(x>y)swap(x,y);
        int a=id[x],b=id[y];
        if(a==b)
        {
            int mx=0,mxx=0;
            for(rg int j=x;j<=y;j++)
            {
                int l=lower_bound(d[c[j]].begin(),d[c[j]].end(),x)-d[c[j]].begin(),r=lower_bound(d[c[j]].begin(),d[c[j]].end(),y)-d[c[j]].begin(),t=r-l+1;
        		if(d[c[j]][r]!=y)t--;
                if(t>mxx||(t==mxx&&mx>c[j]))mx=c[j],mxx=t;
            }
            printf("%d\n",ans=mp[mx]);
        }
        else 
        {
            int mx=0,mxx=0;
            if(x>(a-1)*num+1)
            {
                for(rg int j=x;j<=min(a*num,n);j++)
                {
                    int l=lower_bound(d[c[j]].begin(),d[c[j]].end(),x)-d[c[j]].begin(),r=lower_bound(d[c[j]].begin(),d[c[j]].end(),y)-d[c[j]].begin(),t=r-l+1;
                    if(d[c[j]][r]!=y)t--;
                    if(t>mxx||(t==mxx&&mx>c[j]))mx=c[j],mxx=t;
                }
                a++;
            }
            if(y<min(b*num,n))
            {
                for(rg int j=(b-1)*num+1;j<=y;j++)
                {
                    int l=lower_bound(d[c[j]].begin(),d[c[j]].end(),x)-d[c[j]].begin(),r=lower_bound(d[c[j]].begin(),d[c[j]].end(),y)-d[c[j]].begin(),t=r-l+1;
                    if(d[c[j]][r]!=y)t--;
                    if(t>mxx||(t==mxx&&mx>c[j]))mx=c[j],mxx=t;
                }
                b--;
            }
            if(mxx<g[a][b]||(mxx==g[a][b]&&mx>f[a][b]))mx=f[a][b],mxx=g[a][b];
            printf("%d\n",ans=mp[mx]);
        }
    }
}
posted @ 2019-01-21 21:51  蒟蒻--lichenxi  阅读(250)  评论(0编辑  收藏  举报