• 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
    ",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 }
  • 相关阅读:
    ReactiveCocoa入门教程——第一部分
    How Do I Declare A Block in Objective-C?
    Xcode 6制作动态及静态Framework
    用CocoaPods做iOS程序的依赖管理
    oracle误删除数据恢复
    搭建第一个web项目:quartz+spring实现定时任务
    通过jsoup对网页进行数据抓取。
    使用httpClient模拟登陆开心网过程中登陆成功但是跳转不成功
    service
    搭建第一个web项目:实现用户的增删改查(四)
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/5278117.html
Copyright © 2020-2023  润新知