CodeChef CBAL

题面:

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 }
时间: 2024-12-25 23:14:25

CodeChef CBAL的相关文章

CodeChef FNCS (分块+树状数组)

题目:https://www.codechef.com/problems/FNCS 题解: 我们知道要求区间和的时候,我们用前缀和去优化.这里也是一样,我们要求第 l 个函数到第 r 个函数 [l, r] 的函数和,那么我们可以用 sum[r] - sum[l-1] 来求得. 由于这个数据量有点大,所以我们将函数分块. 例如样例: 1 3 有5个函数,那么我们分成3块.{ [1 3] , [2 5] }, { [4 5], [3 5] }, { [1 2] }.每一块对应都有一个sum ,这时如

codechef营养题 第三弹

第三弾が始まる! codechef problems 第三弹 一.Motorbike Racing 题面 It's time for the annual exciting Motorbike Race in Byteland. There are N motorcyclists taking part in the competition. Johnny is watching the race. At the present moment (time 0), Johnny has taken

codechef 营养题 第一弹

第一弾が始まる! 定期更新しない! 来源:http://wenku.baidu.com/link?url=XOJLwfgMsZp_9nhAK15591XFRgZl7f7_x7wtZ5_3T2peHh5XXoERDanUcdxw08SmRj1a5VY1o7jpW1xYv_V1kuYao1Pg4yKdfG4MfNsNAEa codechef problems 第一弹 一.Authentication Failed原题题面Several days ago Chef decided to registe

bzoj4260: Codechef REBXOR

求异或maxmin一般用trie (二进制式的trie).query中找的是满足((x>>i)&1)^A=1,那么A=((x>>i)&1)^1:maxx=max(sumx,sumi)(i=[1,x]).(YY一下异或的性质 #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #def

Codechef July Challenge 2014部分题解

Dish Owner(并查集) 链接:http://www.codechef.com/JULY14/problems/DISHOWN/ 题意分析:本题主要操作就是给出0 x y时,拥有第x道菜的厨师与拥有第y道菜的厨师pk,谁拥有的所有菜的其中一道菜(不一定是x或y)的分值比较高谁就获胜,并赢得loser的所有菜.即比较的是每个人分值最高的菜,所以对于非loser的人来说,他的分值最高的菜是不变的.综合题意用并查集易解. #include <cstdio> const int Maxn=100

codechef Row and Column Operations 题解

You are given an N × N grid initially filled by zeros. Let the rows and columns of the grid be numbered from1 to N, inclusive. There are two types of operations can be applied to the grid: RowAdd R X: all numbers in the row R should be increased by X

Codechef Nuclear Reactors 题解

There are K nuclear reactor chambers labelled from 0 to K-1. Particles are bombarded onto chamber 0. The particles keep collecting in the chamber 0. However if at any time, there are more than N particles in a chamber, a reaction will cause 1 particl

codechef Cleaning Up 题解

After a long and successful day of preparing food for the banquet, it is time to clean up. There is a list of n jobs to do before the kitchen can be closed for the night. These jobs are indexed from 1 to n. Most of the cooks have already left and onl

codechef Permutation Cycles 题解

We consider permutations of the numbers 1,..., N for some N. By permutation we mean a rearrangment of the number 1,...,N. For example 2  4  5  1  7  6  3  8 is a permutation of 1,2,...,8. Of course, 1  2  3  4  5  6  7  8 is also a permutation of 1,2