P4135 作诗——分块
Posted zinn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P4135 作诗——分块相关的知识,希望对你有一定的参考价值。
题目:https://www.luogu.org/problemnew/show/P4135
分块大法;
块之间记录答案,每一块记录次数前缀和;
注意每次把桶中需要用到位置赋值就好了;
为什么加了特判会 T 一个点?
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int const maxn=1e5+5; int n,c,m,mod,a[maxn],ans,blk[maxn],base,t[maxn],cnt[320][maxn],bst[320],bed[320],f[320][320]; void pre(int x) { int tmp=0,tem=x; memset(t,0,sizeof t); for(int i=bst[x];i<=n;i++) { t[a[i]]++; if(t[a[i]]%2==0)tmp++; else if(t[a[i]]>1)tmp--; if(i==bed[tem])f[x][tem]=tmp,tem++; } } int main() { scanf("%d%d%d",&n,&c,&m); base=sqrt(n); for(int i=1;i<=n;i++)scanf("%d",&a[i]),blk[i]=(i-1)/base+1; for(int i=1;i<=blk[n];i++)bst[i]=(i-1)*base+1,bed[i]=min(n,i*base); for(int i=1;i<=blk[n];i++)pre(i); for(int i=1;i<=blk[n];i++) { for(int k=1;k<=c;k++)cnt[i][k]=cnt[i-1][k]; for(int j=bst[i];j<=bed[i];j++)cnt[i][a[j]]++; } for(int i=1,l,r;i<=m;i++) { scanf("%d%d",&l,&r); l=(l+ans)%n+1; r=(r+ans)%n+1; if(l>r)swap(l,r); // if(l==r){printf("0 "); ans=0; continue;}//ans=0!!! //加特判变慢了??? ans=0; if(blk[l]==blk[r]) { for(int j=l;j<=r;j++)t[a[j]]=0; for(int j=l;j<=r;j++) { t[a[j]]++; if(t[a[j]]%2==0)ans++; else if(t[a[j]]>1)ans--; } printf("%d ",ans); } else { if(blk[r]>blk[l]+1)ans=f[blk[l]+1][blk[r]-1]; for(int j=l;j<=bed[blk[l]];j++)t[a[j]]=cnt[blk[r]-1][a[j]]-cnt[blk[l]][a[j]]; for(int j=bst[blk[r]];j<=r;j++)t[a[j]]=cnt[blk[r]-1][a[j]]-cnt[blk[l]][a[j]]; for(int j=l;j<=bed[blk[l]];j++) { t[a[j]]++; if(t[a[j]]%2==0)ans++; else if(t[a[j]]>1)ans--; } for(int j=bst[blk[r]];j<=r;j++) { t[a[j]]++; if(t[a[j]]%2==0)ans++; else if(t[a[j]]>1)ans--; } printf("%d ",ans); } } return 0; }
以上是关于P4135 作诗——分块的主要内容,如果未能解决你的问题,请参考以下文章