zoukankan      html  css  js  c++  java
  • [Ynoi2019模拟赛]Yuno loves sqrt technology III

    题目大意:

    给你一个长为n的序列am次询问,每次查询一个区间的众数的出现次数,强制在线。

    解题思路:

    出题人题解

    众所周知lxl是个毒瘤,Ynoi道道都是神仙题

    首先得离散化。

    分块后,预处理Fi,j表示第ij块的众数的出现次数。此处要用一个桶,空间复杂度O(n),时间复杂度O(n√n)

    用vector按顺序存每个数值所有元素的出现位置。

    再记录每个元素在相应vector里的下标p

    以上空间复杂度都是O(n)的。

    考虑询问,中间的直接使用预处理出的Fi,j的值即可。设当前的答案ans=Fi,j

    考虑边界的元素。

    显然,由于边界的数最多2n个,所以最多使得答案增加2n。

    我们只需要检查这些边角的元素,每次判断这些数的出现次数能否达到ans+1

    对于左边的边角元素x,我们在相应的vector里找到下标为px+ans的元素yy,若yry⩽r,则说明该数值在范围内有至少ans+1ans+1个数,暴力++ans即可。

    对于右边的边角元素x,我们在相应的vector里找到下标为pxans的元素yy,若yly⩾l,则说明该数值在范围内有至少ans+1ans+1个数,暴力++ans即可。

    每次询问对O(√n)个元素检查,++ans的次数为O(√n)次。所以查询的时间复杂度为O(m√n)

    总时间复杂度O((n+m)√n),空间复杂度O(n),lxl说达到了下界。

    C++ Code:

    #include<cstdio>
    #include<cctype>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    #define siz 708
    #define N 500001
    class istream{
        char buf[20000003],*s;
        public:
            inline istream(){
    #ifndef ONLINE_JUDGE
                freopen("input.txt","r",stdin);
    #endif
                fread(s=buf,1,20000003,stdin);
                fclose(stdin);
            }
            inline istream&operator>>(int&rhs){
                int f=rhs=0;
                for(;!isdigit(*s);++s)f=*s=='-';
                for(;isdigit(*s);)
                rhs=(rhs<<3)+(rhs<<1)+(*s++^'0');
                if(f)rhs=-rhs;
                return*this;
            }
    }cin;
    class ostream{
        char buf[5000005],*s;
        public:
            inline ostream(){s=buf;}
            inline ostream&operator<<(int rhs){
                if(rhs<0)*s++='-',rhs=-rhs;
                if(rhs==0){
                    *s++='0';
                    return*this;
                }
                static int w;
                for(w=1;w<=rhs;w*=10);
                for(w/=10;w;w/=10)*s++=(rhs/w)^'0',rhs%=w;
                return*this;
            }
            inline ostream&operator<<(const char&rhs){*s++=rhs;return*this;}
            inline~ostream(){
                fwrite(buf,1,s-buf,stdout);
            }
    }cout;
    int n,m,L[710],R[710],bel[N],blocks,mx[710][710],ans,tot[N],wz[N],a[N];
    void init(){
        blocks=(n-1)/siz+1;
        for(int i=1;i<=blocks;++i)L[i]=R[i-1]+1,R[i]=i*siz;
        R[blocks]=n;
        for(int i=1;i<=blocks;++i){
            memset(tot,0,sizeof tot);
            for(int j=L[i];j<=R[i];++j)bel[j]=i;
            for(int j=i;j<=blocks;++j){
                int&F=mx[i][j];
                F=mx[i][j-1];
                for(int k=L[j];k<=R[j];++k)
                F=std::max(F,++tot[a[k]]);
            }
        }
    }
    std::vector<int>ls,v[N];
    int main(){
        ls.push_back(-1);
        cin>>n>>m;
        for(int i=1;i<=n;ls.push_back(a[i++]))cin>>a[i];
        std::sort(ls.begin(),ls.end());
        ls.erase(std::unique(ls.begin(),ls.end()),ls.end());
        for(int i=1;i<=n;++i)v[a[i]=std::lower_bound(ls.begin(),ls.end(),a[i])-ls.begin()].push_back(i),wz[i]=v[a[i]].size()-1;
        init();
        memset(tot,0,sizeof tot);
        while(m--){
            int l,r;cin>>l>>r;
            l^=ans,r^=ans;
            ans=0;
            if(bel[l]==bel[r]){
                for(int i=l;i<=r;++i)ans=std::max(ans,++tot[a[i]]);
                for(int i=l;i<=r;++i)tot[a[i]]=0;
            }else{
                ans=mx[bel[l]+1][bel[r]-1];
                for(int i=l;i<=R[bel[l]];++i){
                    int it=wz[i];
                    while(it+ans<v[a[i]].size()&&v[a[i]][it+ans]<=r)++ans;
                }
                for(int i=L[bel[r]];i<=r;++i){
                    int it=wz[i];
                    while(it-ans>=0&&v[a[i]][it-ans]>=l)++ans;
                }
            }
            cout<<ans<<'
    ';
        }
        return 0;
    }
  • 相关阅读:
    Atitit.ati orm的设计and架构总结 适用于java c# php版
    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本
    Atitit.ati dwr的原理and设计 attilax 总结 java php 版本
    Atitit. 软件设计 模式 变量 方法 命名最佳实践 vp820 attilax总结命名表大全
    Atitit. 软件设计 模式 变量 方法 命名最佳实践 vp820 attilax总结命名表大全
    Atitit 插件机制原理与设计微内核 c# java 的实现attilax总结
    Atitit 插件机制原理与设计微内核 c# java 的实现attilax总结
    atitit.基于  Commons CLI 的命令行原理与 开发
    atitit.基于  Commons CLI 的命令行原理与 开发
    atitit.js 与c# java交互html5化的原理与总结.doc
  • 原文地址:https://www.cnblogs.com/zzrblogs/p/10643250.html
Copyright © 2011-2022 走看看