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:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
char ch;
bool ok;
void read(int &x){
for (ok=,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=;
for (x=;isdigit(ch);x=x*+ch-'',ch=getchar());
if (ok) x=-x;
}
typedef long long int64;
const int maxs=;
const int maxn=;
char s[maxn];
int T,n,lim,siz,cnt,q,x,y,op;
int a[maxn],tmp[maxn],bel[maxn];
int64 f[maxs][maxn][],ans[maxs][maxs][],sum[maxn][],A,B;
struct Data{
int l,r;
}block[maxn];
void init(){
for (int i=;i<=n;i++) a[i]=a[i-]^(<<(s[i]-'a'));
memcpy(tmp,a,sizeof(tmp)),sort(tmp,tmp+n+),cnt=unique(tmp,tmp+n+)-tmp;
for (int i=;i<=n;i++) a[i]=upper_bound(tmp,tmp+cnt,a[i])-tmp;
memset(block,-,sizeof(block));
for (int i=;i<=n;i++){
bel[i]=i/siz+;
if (block[bel[i]].l==-) block[bel[i]].l=i;
block[bel[i]].r=i;
}
lim=bel[n];
for (int i=;i<=lim;i++){
for (int j=;j<=cnt;j++) for (int k=;k<=;k++) f[i][j][k]=f[i-][j][k];
for (int j=block[i].l;j<=block[i].r;j++){
f[i][a[j]][]++;
f[i][a[j]][]+=j;
f[i][a[j]][]+=1LL*j*j;
}
}
for (int i=;i<=lim;i++){
for (int j=i;j<=lim;j++){
for (int k=;k<=;k++) ans[i][j][k]=ans[i][j-][k];
for (int k=block[j].l;k<=block[j].r;k++){
ans[i][j][]+=sum[a[k]][];
ans[i][j][]+=1LL*k*sum[a[k]][]-sum[a[k]][];
ans[i][j][]+=1LL*k*k*sum[a[k]][]-2LL*k*sum[a[k]][]+sum[a[k]][];
sum[a[k]][]++;
sum[a[k]][]+=k;
sum[a[k]][]+=1LL*k*k;
}
}
for (int j=;j<=cnt;j++) for (int k=;k<=;k++) sum[j][k]=;
}
}
void query(int l,int r,int op){
if (l>r) swap(l,r); l--;
int st=bel[l],ed=bel[r]; int64 res[]={,,},tmp[];
if (st!=ed){
if (l>block[st].l) st++;
if (r<block[ed].r) ed--;
for (int i=;i<=;i++) res[i]+=ans[st][ed][i];
if (st!=bel[l]){
for (int i=block[bel[l]].r;i>=l;i--){
for (int j=;j<=;j++) tmp[j]=f[ed][a[i]][j]-f[st-][a[i]][j]+sum[a[i]][j];
res[]+=tmp[];
res[]+=tmp[]-1LL*i*tmp[];
res[]+=1LL*i*i*tmp[]-2LL*i*tmp[]+tmp[];
sum[a[i]][]++;
sum[a[i]][]+=i;
sum[a[i]][]+=1LL*i*i;
}
}
if (ed!=bel[r]){
for (int i=block[bel[r]].l;i<=r;i++){
for (int j=;j<=;j++) tmp[j]=f[ed][a[i]][j]-f[st-][a[i]][j]+sum[a[i]][j];
res[]+=tmp[];
res[]+=1LL*i*tmp[]-tmp[];
res[]+=1LL*i*i*tmp[]-2LL*i*tmp[]+tmp[];
sum[a[i]][]++;
sum[a[i]][]+=i;
sum[a[i]][]+=1LL*i*i;
}
}
if (ed!=bel[r]){
for (int i=block[bel[r]].l;i<=r;i++){
sum[a[i]][]--;
sum[a[i]][]-=i;
sum[a[i]][]-=1LL*i*i;
}
}
if (st!=bel[l]){
for (int i=block[bel[l]].r;i>=l;i--){
sum[a[i]][]--;
sum[a[i]][]-=i;
sum[a[i]][]-=1LL*i*i;
}
}
}
else{
if (l==block[st].l&&r==block[ed].r) res[op]=ans[st][ed][op];
else{
for (int i=l;i<=r;i++){
res[]+=sum[a[i]][];
res[]+=1LL*i*sum[a[i]][]-sum[a[i]][];
res[]+=1LL*i*i*sum[a[i]][]-2LL*i*sum[a[i]][]+sum[a[i]][];
sum[a[i]][]++;
sum[a[i]][]+=i;
sum[a[i]][]+=1LL*i*i;
}
for (int i=l;i<=r;i++){
sum[a[i]][]--;
sum[a[i]][]-=i;
sum[a[i]][]-=1LL*i*i;
}
}
}
A=B,B=res[op];
printf("%lld\n",res[op]);
}
int main(){
for (read(T);T;T--){
scanf("%s",s+),n=strlen(s+),siz=sqrt(n),A=B=,init();
for (read(q);q;q--) read(x),x=(x+A)%n+,read(y),y=(y+B)%n+,read(op),query(x,y,op);
}
return ;
}
CodeChef CBAL的更多相关文章
- 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1288 Solved: 490 ...
- 【BZOJ4260】 Codechef REBXOR 可持久化Trie
看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...
- codechef 两题
前面做了这场比赛,感觉题目不错,放上来. A题目:对于数组A[],求A[U]&A[V]的最大值,因为数据弱,很多人直接排序再俩俩比较就过了. 其实这道题类似百度之星资格赛第三题XOR SUM, ...
- codechef January Challenge 2014 Sereja and Graph
题目链接:http://www.codechef.com/JAN14/problems/SEAGRP [题意] 给n个点,m条边的无向图,判断是否有一种删边方案使得每个点的度恰好为1. [分析] 从结 ...
- BZOJ3509: [CodeChef] COUNTARI
3509: [CodeChef] COUNTARI Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 339 Solved: 85[Submit][St ...
- CodeChef FNCS
题面:https://www.codechef.com/problems/FNCS 题解: 我们考虑对 n 个函数进行分块,设块的大小为S. 每个块内我们维护当前其所有函数值的和,以及数组中每个元素对 ...
- codechef Prime Distance On Tree(树分治+FFT)
题目链接:http://www.codechef.com/problems/PRIMEDST/ 题意:给出一棵树,边长度都是1.每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大? 树分治 ...
- BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )
树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...
- BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )
从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献 ...
随机推荐
- jsp+urlrewrite实现html分页简单粗暴实现
今天去检查一同事写的一分页实现,看了有点郁闷,都说了要换成html实现方便搜索引擎收录,他还是用的js,真是晕.还得帮他解决 好吧.言归正传,我在他的基础上粗暴的修改了下,达到了基本的效果,带数字分页 ...
- leetcode第一刷_Triangle
非常easy的一道DP,看到空间限制是O(N)的,不要习惯性的以为是要保存每一行的最小值,不难想到是要保存一行其中各个数为路径终点时的和的大小.当算到最后一行时,就是从顶部究竟部以这个底部位置为终点的 ...
- richTextBoxFontClass
使用 private void button1_Click(object sender, EventArgs e) { RichTextBoxCtrl.richTextBoxFontClass r = ...
- jdk和jre是什么?都有什么用?(转帖)
jdk和jre是什么?都有什么用?(转帖) 文章分类:Java编程 大家肯定在安装JDK的时候会有选择是否安装单独的jre,一般都会一起安装,我也建议大家这样做.由于这样更能帮助大家弄清楚它们的差别: ...
- jvisualvm图解
http://blog.csdn.net/a19881029/article/details/8432368 jvisualvm能干什么:监控内存泄露,跟踪垃圾回收,执行时内存.cpu分析,线程分析. ...
- Linux命令后台执行技巧小结
1.最简单的方法: command & 例如: top & 此时显示job编号和后台进程号 [] 2.正在运行的程序放入后台 Ctrl - Z 3.查看有哪些后台进程及状态 jobs ...
- JS获取URL的参数
function request(paras) { var url = location.href; , url.length).split("&"); var paraO ...
- jquery.qrcode和jqprint的联合使用,实现html生成二维码并打印(中文也ok)
在公司的生产现场中,常常会在一些部品或设备上贴上二维码,用于扫描录入数据,免去手动输入的麻烦. 以前曾经做过winform的程序,生成二维码,并打印出来,使用的是zxing的类库, 但是如果二维码是附 ...
- php错误处理和异常处理
PHP错误处理有两种:标准的错误处理和异常(OOP语法新出现的错误处理机制)
- 自己做的demo---宣告可以在java世界开始自由了
package $interface; public interface ILeaveHome { public abstract int a(); public abstract int b(); ...