bzoj2821 -- 分块

来源:互联网 发布:淘宝 台湾省 编辑:程序博客网 时间:2024/06/03 05:30
将序列分块。

令f[i][j]表示第i块到第j块的答案,可以O(n*sqrt(n))统计出来。

令sum[i][j]表示前i块值为j的数出现了几次。每次询问暴力统计零散的数对答案的贡献就可以了。

具体见代码

代码:

 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 inline char nc(){ 8     static char buf[100000],*p1=buf,*p2=buf; 9     if(p1==p2){10         p2=(p1=buf)+fread(buf,1,100000,stdin);11         if(p1==p2)return EOF;12     }13     return *p1++;14 }15 inline void Read(int& x){16     char c=nc();17     for(;c<'0'||c>'9';c=nc());18     for(x=0;c>='0'&&c<='9';x=(x<<1)+(x<<3)+c-48,c=nc()); 19 }20 char ss[30];21 int Len;22 inline void Print(int x){23     if(x==0)putchar(48);24     for(Len=0;x;x/=10)ss[++Len]=x%10;25     for(;Len;)putchar(ss[Len--]+48);putchar('\n');26 }27 #define N 10001028 #define Sn 32029 int i,j,k,n,m,b[N],Cnt,x,y,Sum[Sn][N],a[N],s,c,f[Sn][Sn],t[N],Ans,A[N],Top,l[N],r[N];30 int main()31 {32     Read(n);Read(c);Read(m);33     s=sqrt((double)n);Cnt=(n-1)/s+1;34     for(i=1;i<=n;i++){35         Read(a[i]);b[i]=(i-1)/s+1;36         for(j=b[i];j<=Cnt;j++)Sum[j][a[i]]++;37         r[b[i]]=i;38     }39     for(i=1;i<=Cnt;i++)l[i]=r[i-1]+1;40     for(i=1;i<=Cnt;i++){41         memset(t,0,sizeof(t));x=0;42         for(j=i;j<=Cnt;j++){43             for(k=l[j];k<=r[j];k++)44             if(t[a[k]]++)x+=(t[a[k]]&1)?-1:1;45             f[i][j]=x;46         }47     }48     while(m--){49         Read(x);Read(y);50         x=(x+Ans)%n+1;y=(y+Ans)%n+1;51         if(x>y)swap(x,y);52         if(b[x]==b[y]){53             Ans=Top=0;54             for(i=x;i<=y;i++)A[++Top]=a[i];55             sort(A+1,A+Top+1);56             for(i=j=1;i<=Top;i=j+1){57                 while(A[j+1]==A[i]&&j<Top)j++;58                 if((j-i+1)%2==0)Ans++;59             }60             Print(Ans);61             continue;62         }63         Ans=f[b[x]+1][b[y]-1];Top=0;64         for(i=x;b[i]==b[x];i++)A[++Top]=a[i];65         for(i=y;b[i]==b[y];i--)A[++Top]=a[i];66         sort(A+1,A+Top+1);67         for(i=j=1;i<=Top;i=j+1){68             while(A[j+1]==A[i]&&j<Top)j++;69             if((j-i+1)%2==0){70                 if(Sum[b[y]-1][A[i]]-Sum[b[x]][A[i]]==0)Ans++;71             }else if((Sum[b[y]-1][A[i]]-Sum[b[x]][A[i]])%2==1)Ans++;else 72             if(Sum[b[y]-1][A[i]]-Sum[b[x]][A[i]]>0)Ans--;73         }74         Print(Ans);75     }76     return 0;77 }
bzoj2821

 

原创粉丝点击