zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",ans=mp[mx]);
            }
        }
    }
    
  • 相关阅读:
    数据结构之链表——加里森的任务(循环链表)
    数据结构之队列——回文字判断
    数据结构之栈——二进制转十进制
    《爱的艺术》人类超越了本能
    从一个Activity返回上一个Activity
    VS(C++)编程遇到的错误集合
    C++(MFC)编程一些注意事项
    Tomcat部署(进行web服务器开发)
    本地IP与宽带IP
    opencv的Mat图像显示在MFC控件中
  • 原文地址:https://www.cnblogs.com/lcxer/p/10301232.html
Copyright © 2011-2022 走看看