zoukankan      html  css  js  c++  java
  • codechef CBAL

    传送门:https://www.codechef.com/problems/CBAL

    思路:

    先求一遍出现次数前缀和,我们只管每个字母出现次数奇偶性,所以可以把状态压缩一下,离散化之后就只有最多n个状态
    对于子串[l,r]如果s[l-1]==s[r],那么[l,r]合法
    f 前i块,状态j,出现下标k次方之和,ans 块i到j的答案
    完整的块直接得答案,外面剩余的一个一个加进来
    假设现在加进来的位置是b,状态为s[b]
    那么对于0次方 就不说什么了,就是s[b]状态的出现次数
    对于1次方 由Σ(b-i)^1=b*sum[i][[0]-sum[i][1](s[i]==s[b])可算得
    对于2次方 由Σ(b-i)^2=(b^2-2*b*sum[i][1]+sum[i][2])(s[i]==s[b])可算得

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<cassert>
    #include<iostream>
    #include<algorithm>
    const int maxn=100010,maxb=320;
    typedef long long ll;
    using namespace std;
    int cas,n,Q,sta[maxn],pw[29],tmp[maxn],cnt,bcnt,bsz,bel[maxn],seq[maxn];char s[maxn];
    ll A,B,lastans,f[maxb][maxn][3],ans[maxb][maxb][3],sum[maxn][3];
    struct seg{int l,r;}blk[maxb];
    
    void init(){
    	pw[0]=1;for (int i=1;i<=26;i++) pw[i]=pw[i-1]<<1;
    	scanf("%s",s+1),n=strlen(s+1),scanf("%d",&Q);
    	sta[0]=tmp[0]=0;
    	for (int i=1;i<=n;i++) sta[i]=sta[i-1]^pw[s[i]-'a'],tmp[i]=sta[i];
    	sort(tmp,tmp+n+1),cnt=unique(tmp,tmp+n+1)-tmp;
    	for (int i=0;i<=n;i++) sta[i]=upper_bound(tmp,tmp+cnt,sta[i])-tmp;
    }
    
    void trans(ll a[],ll sum[],int b,int op){
    	a[0]+=sum[0];
    	a[1]+=op*(sum[0]*b-sum[1]);
    	a[2]+=sum[0]*b*b-2ll*sum[1]*b+sum[2];
    	sum[0]++,sum[1]+=b,sum[2]+=1ll*b*b;
    }
    
    void prework(){
    	for (int i=1;i<maxb;i++) blk[i].l=0;
    	bsz=sqrt(n);
    	for (int i=0;i<=n;i++){
    		bel[i]=i/bsz+1;
    		if (!blk[bel[i]].l) blk[bel[i]].l=i;
    		blk[bel[i]].r=i;
    	}
    	bcnt=bel[n];
    	for (int i=1;i<=bcnt;i++){
    		for (int j=1;j<=cnt;j++) for (int k=0;k<3;k++) f[i][j][k]=f[i-1][j][k];
    		for (int j=blk[i].l;j<=blk[i].r;j++){
    			int st=sta[j];
    			f[i][st][0]++;
    			f[i][st][1]+=j;
    			f[i][st][2]+=1ll*j*j;
    		}
    	}
    	for (int i=1;i<=bcnt;i++){
    		int cnt=0;
    		for (int j=i;j<=bcnt;j++){
    			for (int k=0;k<3;k++) ans[i][j][k]=ans[i][j-1][k];
    			for (int k=blk[j].l;k<=blk[j].r;k++){
    				trans(ans[i][j],sum[sta[k]],k,1);
    				seq[++cnt]=sta[k];
    			}
    		}
    		for (int j=1;j<=cnt;j++) for (int k=0;k<3;k++) sum[seq[j]][k]=0;
    	}
    }
    ll getf(int l,int r,int st,int type){return f[r][st][type]-f[l-1][st][type];}
    
    ll query(int L,int R,int type){
    	int st=bel[L],ed=bel[R],cnt=0;ll res[3]={0,0,0};
    	if (st<ed){
    		for (int i=0;i<3;i++) res[i]=ans[st+1][ed-1][i];
    		for (int i=blk[st].r;i>=L;i--){
    			int stt=sta[i];
    			if (!sum[stt][0]){
    				seq[++cnt]=stt;
    				for (int k=0;k<3;k++)
    					sum[stt][k]=getf(st+1,ed-1,stt,k);
    			}
    			trans(res,sum[stt],i,-1);
    		}
    		for (int i=blk[ed].l;i<=R;i++){
    			int stt=sta[i];
    			if (!sum[stt][0]){
    				seq[++cnt]=stt;
    				for (int k=0;k<3;k++)
    					sum[stt][k]=getf(st+1,ed-1,stt,k);
    			}
    			trans(res,sum[stt],i,1);
    		}
    	}
    	else{
    		for (int i=L;i<=R;i++){
    			int stt=sta[i];
    			if (!sum[stt][0]) seq[++cnt]=stt;
    			trans(res,sum[stt],i,1);
    		}
    	}
    	for (int i=1;i<=cnt;i++) for (int j=0;j<3;j++) sum[seq[i]][j]=0;
    	return res[type];
    }
    
    void work(){
    	lastans=A=B=0;
    	for (int i=1,x,y,type;i<=Q;i++){
    		scanf("%d%d%d",&x,&y,&type);
    		x=(x+A)%n+1,y=(y+B)%n+1;
    		if (x>y) swap(x,y);
    		lastans=query(x-1,y,type);
    		printf("%lld
    ",lastans);
    		A=B,B=lastans;
    	}
    }
    
    int main(){
    	scanf("%d",&cas);
    	while (cas--) init(),prework(),work();
    	return 0;
    }



  • 相关阅读:
    setAnimationTransition:forView:cache: 运行动画时背景色问题
    架构师速成4.6-软技能和硬技能
    Java获取某年某周的第一天
    openssl之BIO系列之12---文件描写叙述符(fd)类型BIO
    centos 使用 CP 命令 不提示 覆盖
    [3 Jun 2015 ~ 9 Jun 2015] Deep Learning in arxiv
    P1314 聪明的质监员
    P2858 [USACO06FEB]奶牛零食Treats for the Cows
    1163 访问艺术馆
    P1352 没有上司的舞会
  • 原文地址:https://www.cnblogs.com/thythy/p/5493641.html
Copyright © 2011-2022 走看看