标签:
题面:
https://www.codechef.com/problems/CBAL
题解:
可以发现,我们关心的仅仅是每个字符出现次数的奇偶性,而且字符集大小仅有 26,
所以我们状态压缩,记 a[i]表示 s[1..i]所有字符的奇偶性状态,
那么子串 s[L..R]是平衡字符串当且仅当a[L-1]=a[R]。
我们对 a 离散化后就可以让其在[1,n]的范围内。
如果没有强制在线,那么我们很容易用莫队算法解决。
记录当前范围所有状态的出现位置下标的 0~2 次方之和,
利用(a-b)2=a2-2ab+b2可以很方便地实现在首尾添加元素。
那么这题强制在线,我们用分块算法即可。
记录 ans[i][j][type]表示块 i~块 j 的 type权值,
f[i][j][k]表示前 i 个块中权值 j 出现位置下标的 k 次方和,
那么查询一个区间我们可以先得到其完整覆盖的块的答案以及状态,
然后用上述方法在块的首尾加入剩下的元素并更新答案即可。
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 char ch; 8 bool ok; 9 void read(int &x){ 10 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch==‘-‘) ok=1; 11 for (x=0;isdigit(ch);x=x*10+ch-‘0‘,ch=getchar()); 12 if (ok) x=-x; 13 } 14 typedef long long int64; 15 const int maxs=320; 16 const int maxn=100005; 17 char s[maxn]; 18 int T,n,lim,siz,cnt,q,x,y,op; 19 int a[maxn],tmp[maxn],bel[maxn]; 20 int64 f[maxs][maxn][3],ans[maxs][maxs][3],sum[maxn][3],A,B; 21 struct Data{ 22 int l,r; 23 }block[maxn]; 24 void init(){ 25 for (int i=1;i<=n;i++) a[i]=a[i-1]^(1<<(s[i]-‘a‘)); 26 memcpy(tmp,a,sizeof(tmp)),sort(tmp,tmp+n+1),cnt=unique(tmp,tmp+n+1)-tmp; 27 for (int i=0;i<=n;i++) a[i]=upper_bound(tmp,tmp+cnt,a[i])-tmp; 28 memset(block,-1,sizeof(block)); 29 for (int i=0;i<=n;i++){ 30 bel[i]=i/siz+1; 31 if (block[bel[i]].l==-1) block[bel[i]].l=i; 32 block[bel[i]].r=i; 33 } 34 lim=bel[n]; 35 for (int i=1;i<=lim;i++){ 36 for (int j=1;j<=cnt;j++) for (int k=0;k<=2;k++) f[i][j][k]=f[i-1][j][k]; 37 for (int j=block[i].l;j<=block[i].r;j++){ 38 f[i][a[j]][0]++; 39 f[i][a[j]][1]+=j; 40 f[i][a[j]][2]+=1LL*j*j; 41 } 42 } 43 for (int i=1;i<=lim;i++){ 44 for (int j=i;j<=lim;j++){ 45 for (int k=0;k<=2;k++) ans[i][j][k]=ans[i][j-1][k]; 46 for (int k=block[j].l;k<=block[j].r;k++){ 47 ans[i][j][0]+=sum[a[k]][0]; 48 ans[i][j][1]+=1LL*k*sum[a[k]][0]-sum[a[k]][1]; 49 ans[i][j][2]+=1LL*k*k*sum[a[k]][0]-2LL*k*sum[a[k]][1]+sum[a[k]][2]; 50 sum[a[k]][0]++; 51 sum[a[k]][1]+=k; 52 sum[a[k]][2]+=1LL*k*k; 53 } 54 } 55 for (int j=1;j<=cnt;j++) for (int k=0;k<=2;k++) sum[j][k]=0; 56 } 57 } 58 void query(int l,int r,int op){ 59 if (l>r) swap(l,r); l--; 60 int st=bel[l],ed=bel[r]; int64 res[3]={0,0,0},tmp[3]; 61 if (st!=ed){ 62 if (l>block[st].l) st++; 63 if (r<block[ed].r) ed--; 64 for (int i=0;i<=2;i++) res[i]+=ans[st][ed][i]; 65 if (st!=bel[l]){ 66 for (int i=block[bel[l]].r;i>=l;i--){ 67 for (int j=0;j<=2;j++) tmp[j]=f[ed][a[i]][j]-f[st-1][a[i]][j]+sum[a[i]][j]; 68 res[0]+=tmp[0]; 69 res[1]+=tmp[1]-1LL*i*tmp[0]; 70 res[2]+=1LL*i*i*tmp[0]-2LL*i*tmp[1]+tmp[2]; 71 sum[a[i]][0]++; 72 sum[a[i]][1]+=i; 73 sum[a[i]][2]+=1LL*i*i; 74 } 75 } 76 if (ed!=bel[r]){ 77 for (int i=block[bel[r]].l;i<=r;i++){ 78 for (int j=0;j<=2;j++) tmp[j]=f[ed][a[i]][j]-f[st-1][a[i]][j]+sum[a[i]][j]; 79 res[0]+=tmp[0]; 80 res[1]+=1LL*i*tmp[0]-tmp[1]; 81 res[2]+=1LL*i*i*tmp[0]-2LL*i*tmp[1]+tmp[2]; 82 sum[a[i]][0]++; 83 sum[a[i]][1]+=i; 84 sum[a[i]][2]+=1LL*i*i; 85 } 86 } 87 if (ed!=bel[r]){ 88 for (int i=block[bel[r]].l;i<=r;i++){ 89 sum[a[i]][0]--; 90 sum[a[i]][1]-=i; 91 sum[a[i]][2]-=1LL*i*i; 92 } 93 } 94 if (st!=bel[l]){ 95 for (int i=block[bel[l]].r;i>=l;i--){ 96 sum[a[i]][0]--; 97 sum[a[i]][1]-=i; 98 sum[a[i]][2]-=1LL*i*i; 99 } 100 } 101 } 102 else{ 103 if (l==block[st].l&&r==block[ed].r) res[op]=ans[st][ed][op]; 104 else{ 105 for (int i=l;i<=r;i++){ 106 res[0]+=sum[a[i]][0]; 107 res[1]+=1LL*i*sum[a[i]][0]-sum[a[i]][1]; 108 res[2]+=1LL*i*i*sum[a[i]][0]-2LL*i*sum[a[i]][1]+sum[a[i]][2]; 109 sum[a[i]][0]++; 110 sum[a[i]][1]+=i; 111 sum[a[i]][2]+=1LL*i*i; 112 } 113 for (int i=l;i<=r;i++){ 114 sum[a[i]][0]--; 115 sum[a[i]][1]-=i; 116 sum[a[i]][2]-=1LL*i*i; 117 } 118 } 119 } 120 A=B,B=res[op]; 121 printf("%lld\n",res[op]); 122 } 123 int main(){ 124 for (read(T);T;T--){ 125 scanf("%s",s+1),n=strlen(s+1),siz=sqrt(n),A=B=0,init(); 126 for (read(q);q;q--) read(x),x=(x+A)%n+1,read(y),y=(y+B)%n+1,read(op),query(x,y,op); 127 } 128 return 0; 129 }
标签:
原文地址:http://www.cnblogs.com/chenyushuo/p/5278117.html