zoukankan      html  css  js  c++  java
  • 洛谷P4135 作诗(分块)

    典型的分块例题,和区间众数差不多,本题必须用不带log的做法,因此我们考虑前缀和,因为显然的是,区间中某数的个数都可以用前缀和表示

    我们设计一个前缀和表示前i块数j的个数是多少个

    然后设计一个d数组表示i-j块之间的答案是多少,这就是分块的基本思想,大块直接维护答案,小块暴力枚举

    之后在暴力枚举的时候,通过奇偶来判断答案

    我的写法常数有点大,估计是多了一个没有必要的离散化。吸吸氧气就能过了

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<map>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    const int mod=1e9+7;
    int d[320][320];
    int s[320][100010];
    int cnt[N];
    int n,c,m;
    int a[N];
    vector<int> b;
    int block;
    void init(){
        block=sqrt(n);
        int l,r;
        for(l=1;l<=n;l++){
            if((l-1)%block==0){
                for(r=1;r<=(int)b.size();r++){
                    s[(l-1)/block+1][r]=s[(l-1)/block][r];
                }
            }
            s[(l-1)/block+1][a[l]]++;
        }
        for(l=1;l<=n;l+=block){
            memset(cnt,0,sizeof cnt);
            int res=0;
            for(r=l;r<=n;r++){
                cnt[a[r]]++;
                if(cnt[a[r]]%2==0)
                    res++;
                if(cnt[a[r]]%2&&cnt[a[r]]>1)
                    res--;
                if(r%block==0||r==n)
                    d[(l-1)/block+1][(r-1)/block+1]=res;
            }
        }
        for(int i=1;i<=n;i++)
            cnt[a[i]]=0;
        /*for(int i=1;i<=(n-1)/block+1;i++){
            for(int j=i;j<=(n-1)/block+1;j++)
                cout<<d[i][j]<<" ";
            cout<<endl;
        }*/
    }
    int cal(int l,int r,int x){
        return s[r][x]-s[l][x];
    }
    int query(int l,int r){
        int idx1=(l-1)/block+1;
        int idx2=(r-1)/block+1;
        int ans=0;
        int i,j;
        if(idx1+1<idx2)
            ans=d[idx1+1][idx2-1];
        if(idx1==idx2){
            for(i=l;i<=r;i++){
                if(cnt[a[i]]){
                    if(cnt[a[i]]&1)
                        ans++;
                    else
                        ans--;
                }
                cnt[a[i]]++;
            }
            for(i=l;i<=r;i++)
                cnt[a[i]]=0;
        }
        else{
            for(i=l;i<=idx1*block;i++){
                if(!cnt[a[i]])
                    cnt[a[i]]=cal(idx1,idx2-1,a[i]);
                if(cnt[a[i]]){
                    if(cnt[a[i]]&1)
                        ans++;
                    else
                        ans--;
                }
                cnt[a[i]]++;
            }
            for(i=(idx2-1)*block+1;i<=r;i++){
                if(!cnt[a[i]])
                    cnt[a[i]]=cal(idx1,idx2-1,a[i]);
                if(cnt[a[i]]){
                    if(cnt[a[i]]&1)
                        ans++;
                    else
                        ans--;
                }
                cnt[a[i]]++;
            }
            for(i=l;i<=idx1*block;i++)
                cnt[a[i]]=0;
            for(i=(idx2-1)*block+1;i<=r;i++)
                cnt[a[i]]=0;
    
        }
    
        return ans;
    }
    int main(){
        cin>>n>>c>>m;
        int i;
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            b.push_back(a[i]);
        }
        sort(b.begin(),b.end());
        b.erase(unique(b.begin(),b.end()),b.end());
        for(i=1;i<=n;i++){
            a[i]=lower_bound(b.begin(),b.end(),a[i])-b.begin()+1;
        }
        init();
        int last=0;
        int l,r;
        while(m--){
            scanf("%d%d",&l,&r);
            l=(l+last)%n+1;
            r=(r+last)%n+1;
            if(l>r)
                swap(l,r);
            last=query(l,r);
            printf("%d
    ",last);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    【SDOI2019】—世界地图(虚树+Kruscal)
    【SDOI2019】—世界地图(虚树+Kruscal)
    【SDOI2019】—热闹的聚会与尴尬的聚会(图论)
    【SDOI2019】—热闹的聚会与尴尬的聚会(图论)
    【BZOJ3153】—Sone1(Top-Tree)
    【BZOJ3153】—Sone1(Top-Tree)
    【UOJ #284】— 快乐游戏鸡(长链剖分+线段树)
    【UOJ #284】— 快乐游戏鸡(长链剖分+线段树)
    【BZOJ4372】—烁烁的游戏(动态点分治)
    【BZOJ4372】—烁烁的游戏(动态点分治)
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12768091.html
Copyright © 2011-2022 走看看