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 }

 

转载于:https://www.cnblogs.com/chenyushuo/p/5278117.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
辽B代驾管理系统对代驾订单管理、用户咨询管理、代驾订单评价管理、代驾订单投诉管理、字典管理、论坛管理、公告管理、新闻信息管理、司机管理、用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行辽B代驾管理系统程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。辽B代驾管理系统的开发让用户查看代驾订单信息变得容易,让管理员高效管理代驾订单信息。 辽B代驾管理系统具有管理员角色,用户角色,这几个操作权限。 辽B代驾管理系统针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理代驾订单信息,管理公告信息等内容。 辽B代驾管理系统针对用户设置的功能有:查看并修改个人信息,查看代驾订单信息,查看公告信息等内容。 辽B代驾管理系统针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理代驾订单信息,管理公告信息等内容。 辽B代驾管理系统针对用户设置的功能有:查看并修改个人信息,查看代驾订单信息,查看公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看代驾订单,删除代驾订单操作,新增代驾订单操作,修改代驾订单操作。公告信息管理页面提供的功能操作有:新增公告,修改公告,删除公告操作。公告类型管理页面显示所有公告类型,在此页面既可以让管理员添加新的公告信息类型,也能对已有的公告类型信息执行编辑更新,失效的公告类型信息也能让管理员快速删除。新闻管理页面,此页面提供给管理员的功能有:新增新闻,修改新闻,删除新闻。新闻类型管理页面,此页面提供给管理员的功能有:新增新闻类型,修改新闻类型,删除新闻类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值