zoukankan      html  css  js  c++  java
  • 【题解】[Violet]蒲公英

    [Violet]蒲公英

    ( ext{Solution:})

    简单分块。由于信息不具有区间可减性一类的东西,线段树一类就不好维护了,考虑用分块来维护。

    首先将值离散化,然后考虑预处理:(p[i][j]) 表示前 (i) 个块中 (j) 的出现次数, (s[i][j]) 表示块 (i,j) 之间的最小众数。

    那么当询问两个区间的时候,涉及到的答案候选就只有左右散块的部分以及中间连续段的最小众数了。

    (p[i][j]) 可以 (O(nsqrt{n})) 预处理出来, (s[i][j]) 考虑枚举 (i,j) 块并暴力更新块内元素 可以 (O(nsqrt{n})) 预处理。

    考虑如何处理询问,当两块之间的间隔小于一个块的时候,暴力就可以做到 (O(sqrt{n})) 级别复杂度了。

    否则考虑暴力处理两端散块,用 (p) 数组获得中间连续段的数字出现次数,加上散块的来更新答案即可。

    代码中不知道是不是有一些边界问题,改了一下块长就过了。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int N=1e5+10;
    int B,bk[N],lastans;
    int p[500][N],b[N],blen,bcnt,s[500][500];
    int n,m,a[N],num,cnt[N],vis[N];
    inline int Min(int x,int y){return x<y?x:y;}
    inline int Max(int x,int y){return x>y?x:y;}
    inline int getpos(int x){return lower_bound(b+1,b+blen+1,x)-b;}
    vector<int>use;
    int query(int l,int r){
        int L=bk[l];
        int R=bk[r];
        use.clear();
        if(R-L<=1){
            for(int i=l;i<=r;++i){
                if(!vis[a[i]])use.push_back(a[i]);
                vis[a[i]]++;
            }
            int pos=-1,ct=-1;
            for(auto i:use){
                if(vis[i]>ct){
                    ct=vis[i];
                    pos=i;
                }
                else if(vis[i]==ct&&i<pos)pos=i;
                vis[i]=0;
            }
            return pos;
        }
        int pos=s[bk[l]+1][bk[r]-1];
        int ct=p[bk[r]-1][pos]-p[bk[l]][pos];
        for(int i=l;i<=Min(bk[l]*B,n);++i){
            if(!vis[a[i]])use.push_back(a[i]);
            vis[a[i]]++;
        }
        for(int i=(bk[r]-1)*B+1;i<=r;++i){
            if(!vis[a[i]])use.push_back(a[i]);
            vis[a[i]]++;
        }
        for(auto i:use){
            if(vis[i]+p[bk[r]-1][i]-p[bk[l]][i]>ct){
                ct=vis[i]+p[bk[r]-1][i]-p[bk[l]][i];
                pos=i;
            }
            else if(vis[i]+p[bk[r]-1][i]-p[bk[l]][i]==ct&&i<pos)pos=i;
            vis[i]=0;
        }
        return pos;
    }
    void File(){
        freopen("in.txt","r",stdin);
        freopen("My.out","w",stdout);
    }
    signed main(){
        // File();
        scanf("%lld%lld",&n,&m);B=sqrt(n)+100;
        for(int i=1;i<=n;++i)scanf("%lld",&a[i]),b[++bcnt]=a[i];
        sort(b+1,b+bcnt+1);
        blen=unique(b+1,b+bcnt+1)-b-1;
        for(int i=1;i<=n;++i)a[i]=getpos(a[i]);
        for(int i=1;i<=n;++i){
            bk[i]=(i-1)/B+1;
            p[bk[i]][a[i]]++;
        }
        num=(n-1)/B+1;
        for(int i=1;i<=B;++i)
            for(int j=1;j<=blen;++j)
                p[i][j]+=p[i-1][j];
        for(int i=1;i<=num;++i){
            for(int j=1;j<=blen;++j)cnt[j]=0;
            int col=-1,ct=0;
            for(int j=i;j<=num;++j){
                for(int k=(j-1)*B+1;k<=Min(n,j*B);++k){
                    cnt[a[k]]++;
                    if(cnt[a[k]]>ct){
                        ct=cnt[a[k]];
                        col=a[k];
                    }
                    else if(cnt[a[k]]==ct&&a[k]<col)col=a[k];
                }
                s[i][j]=col;
            }
        }
        while(m--){
            int l,r;
            scanf("%lld%lld",&l,&r);
            l=(l+lastans-1)%n+1;
            r=(r+lastans-1)%n+1;
            if(l>r)swap(l,r);
            // printf("[%lld %lld]
    ",l,r);
            // for(int i=l;i<=r;++i)printf("%lld ",b[a[i]]);
            // puts("");
            lastans=b[query(l,r)];
            printf("%lld
    ",lastans);
        }
        return 0;
    }
    
  • 相关阅读:
    How to change hostname on SLE
    How to install starDIct on suse OS?
    python logging usage
    How to reset password for unknow root
    How to use wget ?
    How to only capute sub-matched character by grep
    How to inspect who is caller of func and who is the class of instance
    How to use groovy script on jenkins
    Vim ide for shell development
    linux高性能服务器编程 (二) --IP协议详解
  • 原文地址:https://www.cnblogs.com/h-lka/p/15158623.html
Copyright © 2011-2022 走看看