1. 程式人生 > >BZOJ 2821: 作詩(Poetize) | 分塊

BZOJ 2821: 作詩(Poetize) | 分塊

turn blank ast target last swa 分塊 style space

題目:

http://www.lydsy.com/JudgeOnline/problem.php?id=2821


分塊.

預處理:

ans[i][j]表示i塊到j塊的答案;

cnt[i][j]表示i數前j塊出現的次數

詢問:

ret=l到r包含的整塊部分答案,然後暴力處理塊外的數出現次數.

我們發現關於每個數x以下情況可以影響到答案

1.x出現奇數次,整塊中出現了正偶數次,ret--

2.x出現奇數次,整塊中出現了奇數次,ret++

3.x出現偶數次,整塊中出現了奇數次,ret++

而x在整塊出現次數可以用cnt輕松的求出

#include<cstdio>
#include<algorithm>
#include
<cstring> #include<cmath> #define N 100005 #define sq 320 using namespace std; int cnt[N][sq],sum[N],n,c,m,S,s,bl[N],br[N],a[N],ans[sq][sq],lastans, vis[N]; void Init() { for (int i=0;i<n;i++) if (i%S==0) br[s]=i-1,bl[++s]=i; br[s]=n-1,bl[s+1]=br[s+1]=n; for (int i=1;i<=s;i++) {
for (int j=1;j<=c;j++) cnt[j][i]=cnt[j][i-1]; for (int h=bl[i],t=br[i];h<=t;h++) cnt[a[h]][i]=++sum[a[h]]; } memset(sum,0,sizeof(sum)); for (int i=1;i<=s;i++) { int k=bl[i],tmp=0,t,c; for (int j=k;j<n;j++) sum[a[j]]=0; for (int j=i;j<=s;j++) { t
=br[j]; for (;k<=t;k++) { if (vis[a[k]]==i) { c=++sum[a[k]]; if (c%2==0) tmp++; else tmp--; } else vis[a[k]]=i,sum[a[k]]=1; } ans[i][j]=tmp; } } memset(vis,0,sizeof(vis)); } int Query(int l,int r) { if (r-l<2*S) { int tmp=0; for (int i=l;i<=r;i++) if (!vis[a[i]]) vis[a[i]]=1,sum[a[i]]=1; else ++sum[a[i]]; for (int i=l;i<=r;i++) if (vis[a[i]]) tmp+=!(sum[a[i]]%2),vis[a[i]]=0; return tmp; } int L=l/S+1,R=r/S+1; if (l==bl[L]) L--; if (r==br[R]) R++; int st=bl[R],ed=br[L],res=ans[L+1][R-1]; for (int i=l;i<=ed;i++) if (!vis[a[i]]) vis[a[i]]=1,sum[a[i]]=1; else sum[a[i]]++; for (int i=st;i<=r;i++) if (!vis[a[i]]) vis[a[i]]=1,sum[a[i]]=1; else sum[a[i]]++; for (int i=l;i<=ed;i++) if (vis[a[i]]) { int cnt1=sum[a[i]],cnt2=cnt[a[i]][R-1]-cnt[a[i]][L]; if (cnt2>0 && cnt2%2==0 && cnt1%2==1) res--; if (cnt2==0 && cnt1%2==0) res++; if (cnt2%2==1 && cnt1%2==1) res++; sum[a[i]]=vis[a[i]]=0; } for (int i=st;i<=r;i++) if (vis[a[i]]) { int cnt1=sum[a[i]],cnt2=cnt[a[i]][R-1]-cnt[a[i]][L]; if (cnt2>0 && cnt2%2==0 && cnt1%2==1) res--; if (cnt2==0 && cnt1%2==0) res++; if (cnt2%2==1 && cnt1%2==1) res++; sum[a[i]]=vis[a[i]]=0; } return res; } int main() { scanf("%d%d%d",&n,&c,&m);S=sqrt(n); for (int i=0;i<n;i++) scanf("%d",a+i); Init(); for (int i=1,l,r;i<=m;i++) { scanf("%d%d",&l,&r); l=(l+lastans)%n+1; r=(r+lastans)%n+1; if (l>r) swap(l,r); printf("%d\n",lastans=Query(l-1,r-1)); } return 0; }

BZOJ 2821: 作詩(Poetize) | 分塊