bzoj2821: 作诗(Poetize)

分块~好麻烦

就像区间众数那题一样来

用vector+二分来判区间每个数出现的个数

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;

int n,a[110000];
int block,st[110000];

int f[410][410];
int tim,ti[110000];bool v[101000];

vector<int>vec[110000];int le[110000];
int ifodd(int x,int y,int m)
{
    if(x>y)return 0;
    int l=0,r=le[m]-1,as1=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(vec[m][mid]<=x)
        {
            as1=mid+1;
            l=mid+1;
        }
        else r=mid-1;
    }
    l=0,r=le[m]-1;int as2=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(vec[m][mid]<=y)
        {
            as2=mid+1;
            l=mid+1;
        }
        else r=mid-1;
    }
    return (as2==as1)?(-1):((as2-as1)&1);
}

int main()
{
    freopen("poetize.in","r",stdin);
    freopen("poetize.out","w",stdout);
    int Q,C;
    scanf("%d%d%d",&n,&C,&Q); block=(int(sqrt(double(n+1))))+1;
    memset(le,0,sizeof(le));
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]); st[i]=(i-1)/block+1;
        vec[a[i]].push_back(i);le[a[i]]++;
    }
    
    tim=0;
    memset(ti,0,sizeof(ti));
    for(int i=1;i<=block;i++)
    {
        int j=i,cc=0; tim++;
        int be=(i-1)*block+1;
        for(int k=be;k<=n;k++)
        {
            if(st[k]!=st[k-1]&&k!=be)
            {
                f[i][j]=cc;
                j++;
            }
            
            if(tim!=ti[a[k]])
            {
                ti[a[k]]=tim;
                v[a[k]]=0;cc++;
            }
            v[a[k]]^=1;
            if(v[a[k]]==0)cc++;
            else cc--;
        }
        f[i][j]=cc;
    }
    
    //---------------init---------------------
    
    int l,r,ans=0;
    while(Q--)
    {
        scanf("%d%d",&l,&r);
        l=(l+ans)%n+1,r=(r+ans)%n+1;
        if(l>r)swap(l,r);
        
        ans=0; tim++;
        if(st[l]==st[r])
        {
            for(int k=l;k<=r;k++)
            {
                if(tim!=ti[a[k]])
                {
                    ti[a[k]]=tim;
                    v[a[k]]=0;ans++;
                }
                v[a[k]]^=1;
                if(v[a[k]]==0)ans++;
                else ans--;
            }
        }
        else
        {
            if(st[l]+1<=st[r]-1)ans=f[st[l]+1][st[r]-1];
            for(int k=l;k<=st[l]*block;k++)
            {
                if(tim!=ti[a[k]])
                {
                    ti[a[k]]=tim;
                    int d=ifodd(st[l]*block,(st[r]-1)*block,a[k]);
                    if(d<=0)
                    {
                        if(d==-1)ans++;
                        v[a[k]]=0;
                    }
                    else v[a[k]]=1;
                }
                v[a[k]]^=1;
                if(v[a[k]]==0)ans++;
                else ans--;
            }
            for(int k=(st[r]-1)*block+1;k<=r;k++)
            {
                if(tim!=ti[a[k]])
                {
                    ti[a[k]]=tim;
                    int d=ifodd(st[l]*block,(st[r]-1)*block,a[k]);
                    if(d<=0)
                    {
                        if(d==-1)ans++;
                        v[a[k]]=0;
                    }
                    else v[a[k]]=1;
                }
                v[a[k]]^=1;
                if(v[a[k]]==0)ans++;
                else ans--;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

 

 

posted @ 2018-08-07 20:43  AKCqhzdy  阅读(154)  评论(0编辑  收藏  举报