• P4168 [Violet]蒲公英


    P4168 [Violet]蒲公英

    分块

    吸了氧气才过

    强制在线区间众数,具体见hzwer的解题报告(右转Baidu)

    先把数字离散化

    然后对于每个数字开个动态数组存出现的位置

    每次对完整块的众数和不完整块的所有数在动态数组中进行查询,答案必定在它们之中

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<cmath>
    #include<map>
    #include<cctype>
    using namespace std;
    inline int Int(){
        char c=getchar(); int x=0;
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
        return x;
    }
    inline int min(int &a,int &b) {return a<b ?a:b;}
    int n,m,ans,mxd,cnt,_blo,blo[40002],a[40002],f[210][210],mp[40002],ct[40002];
    vector <int> v[40002];
    map <int,int> Map;
    inline void pre(int x){ //预处理整块的区间众数
        memset(ct,0,sizeof(ct)); int mx=0,t=0;
        for(int i=(x-1)*_blo+1;i<=n;++i){
            ++ct[a[i]];
            if(ct[a[i]]>mx||(mx==ct[a[i]]&&mp[a[i]]<mp[t])) t=a[i],mx=ct[a[i]];
            f[x][blo[i]]=t; //第x块到blo[i]块之间的众数
        }
    }
    inline int find(int l,int r,int k){ //区间内出现的次数
        return upper_bound(v[k].begin(),v[k].end(),r)-lower_bound(v[k].begin(),v[k].end(),l);
    }
    inline void query(int l,int r){
        ans=f[blo[l]+1][blo[r]-1];
        mxd=find(l,r,ans); //完整块的众数
        for(int i=min(blo[l]*_blo,r);i>=l;--i){ //对于不完整的块,对所有数暴力查询
            int t=find(l,r,a[i]);
            if(t>mxd||(t==mxd&&mp[a[i]]<mp[ans])) mxd=t,ans=a[i];
        }
        if(blo[l]==blo[r]) return ;
        for(int i=(blo[r]-1)*_blo+1;i<=r;++i){
            int t=find(l,r,a[i]);
            if(t>mxd||(t==mxd&&mp[a[i]]<mp[ans])) mxd=t,ans=a[i];
        }
    }
    int main(){
        n=Int(); m=Int(); _blo=sqrt(n); int q1,q2;
        for(int i=1;i<=n;++i){
            a[i]=Int();
            if(!Map[a[i]]) Map[a[i]]=++cnt,mp[cnt]=a[i];
            a[i]=Map[a[i]]; //离散化
            v[a[i]].push_back(i);
            blo[i]=(i-1)/_blo+1;
        }
        for(int i=1;i<=blo[n];++i) pre(i);
        for(int i=1;i<=m;++i){
            q1=Int(); q2=Int();
            q1=(q1+ans-1)%n+1,q2=(q2+ans-1)%n+1;
            if(q1>q2) swap(q1,q2);
            query(q1,q2); ans=mp[ans];
            printf("%d
    ",ans);
        } return 0;
    }
  • 相关阅读:
    在给定的区间上对每个数都开方 最后还是在一段上求和
    简单的覆盖问题,,通过覆盖的g不同 有这不同的价值 最后还是一段上求和
    codevs 3094 寻找sb4
    noi 04:网线主管
    codevs 1031 质数环
    codevs 1061 重复子串
    codevs 1204 寻找子串位置
    codevs 3223 素数密度
    各种用法
    codevs1073 家族
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/9652989.html
Copyright © 2020-2023  润新知