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条边有贡献 ...
随机推荐
- ABAP程序的效率(转)
在网上看到的一篇文章: 程序的效率是每个程序员都应该重视的,无论您是采用哪一种语言进行开发. 程序有时候越短,并不一定越快,有时候程序很多代码,但不一定会很慢. 性能是一把双刃剑, 获得时间效率的同时 ...
- 简约的返回顶部效果(jQuery)
博客建好也快一个月了,主题是在原有主题的基础上做的修改,喜欢这样的清新简约风格,为了更好的体验,以后也会经常做修改. 一般博客的文章都比较长,看到下面不能快速返回到顶部还真是不方便,今天自己动手写了一 ...
- JS获取和设置光标的位置
<html> <head> <script language="javascript"> function getCursortPosition ...
- [rxjs] Creating An Observable with RxJS
Create an observable var Observable = Rx.Observable; var source = Observable.create(function(observe ...
- marquee 标签的使用详情
<marquee>标签,它是成对出现的标签,首标签<marquee>和尾标签</marquee>之间的内容就是滚动内容.<marquee>标签的属性主要 ...
- 使用Broadcast实现android组件之间的通信 分类: android 学习笔记 2015-07-09 14:16 110人阅读 评论(0) 收藏
android组件之间的通信有多种实现方式,Broadcast就是其中一种.在activity和fragment之间的通信,broadcast用的更多本文以一个activity为例. 效果如图: 布局 ...
- 第一篇:web之前端之html
前端之html 前端之html 本节内容 前端概述 html结构 标签探秘 <!DOCTYPE html>标签 head标签 body标签 1.前端概述 一个web服务的组成分为前端和 ...
- PHP 基础语法 常量 变量
PHP基础语法 标记 当解析一个文件时,PHP 会寻找起始和结束标记,也就是 <?php 和 ?>,这告诉 PHP 开始和停止解析二者之间的代码.此种解析方式使得 PHP 可以被嵌入到各种 ...
- PHP+jQuery+Ajax实现用户登录与退…
用户登录与退出功能应用在很多地方,而在有些项目中,我们需要使用Ajax方式进行登录,登录成功后只刷新页面局部,从而提升了用户体验度.本文将使用PHP和jQuery来实现登录和退出功能. 查看演示DEM ...
- 9张思维导图学习Javascript(转)
思维导图小tips:思维导图又叫心智图,是表达发射性思维的有效的图形思维工具 ,它简单却又极其有效,是一种革命性的思维工具.思维导图运用图文并重的技巧,把各级主题的关系用相互隶属与相关的层级图表现出来 ...