bzoj-1125 Poc

来源:互联网 发布:加拿大经济数据 编辑:程序博客网 时间:2024/06/03 19:05

题意:

给出n个字符串,长度均为len;

有m次操作,每次将两个字符交换;

求每个字符串在任何时点上,与相同的它最多的字符串个数;

n<=1000,len<=100,m<=100000;


题解:

Poi!

字符串长度很小,我们先考虑到用Hash来判断字符串的相同;

这些部分很简单,但是统计任意时点对某个字符串的答案是很难的;

因为如果暴力更新的话复杂度是O(nm),所以不能这么搞;

而延迟更新也没有什么好办法,只能去找打标记的数据结构了;

这里我写了一个Splay,以Hash值大小为关键字排序;

修改时先将其转到根删掉,然后再修改之后插回去,

之后将Hash值相同的一段提出来打标记更新答案;

这样每次的复杂度是O(len+logn)的。。

注意将同一个字符串中的字符交换时,不要让它被删两次哦2333;


代码:


#include<stdio.h>#include<string.h>#include<algorithm>#define N 1100#define seed 1331#define which(x) (ch[fa[x]][1]==x)using namespace std;typedef unsigned long long ll;int n,len;int size[N],fa[N],ch[N][2],cov[N],ans[N],root;char str[N][111];ll val[N],pow[111];void Pushup(int x){size[x]=size[ch[x][0]]+size[ch[x][1]]+1;}void Pushdown(int x){if(cov[x]){ans[ch[x][0]]=max(ans[ch[x][0]],cov[x]);cov[ch[x][0]]=max(cov[ch[x][0]],cov[x]);ans[ch[x][1]]=max(ans[ch[x][1]],cov[x]);cov[ch[x][1]]=max(cov[ch[x][1]],cov[x]);cov[x]=0;}}void Rotate(int x){int f=fa[x];bool k=which(x);Pushdown(f),Pushdown(x);ch[f][k]=ch[x][!k];ch[x][!k]=f;ch[fa[f]][which(f)]=x;fa[x]=fa[f];fa[f]=x;fa[ch[f][k]]=f;Pushup(f);Pushup(x);}void Splay(int x,int g){while(fa[x]!=g){int f=fa[x];if(fa[f]==g){Rotate(x);break;}if(which(x)^which(f))Rotate(x);elseRotate(f);Rotate(x);}if(!g)root=x;}int pre(ll v){int p=root,ret=root;while(p){if(v>val[p])ret=p,p=ch[p][1];elsep=ch[p][0];}return ret;}int sub(ll v){int p=root,ret;while(p){if(v<val[p])ret=p,p=ch[p][0];elsep=ch[p][1];}return ret;}void Down(int x){if(!x)return ;Pushdown(x);Down(ch[x][0]);Down(ch[x][1]);}void Insert(int x){int l=pre(val[x]),r=sub(val[x]);Splay(l,0),Splay(r,l);int t=ch[r][0];fa[t]=x,ch[x][0]=t;fa[x]=r,ch[r][0]=x;Pushup(x),Pushup(r),Pushup(l);ans[x]=max(ans[x],size[x]);cov[x]=max(cov[x],size[x]);}void del(int x){Splay(x,0);int p=ch[x][1];while(ch[p][0])p=ch[p][0];Splay(p,x);ch[p][0]=ch[x][0];fa[ch[p][0]]=p,fa[p]=0;root=p;Pushup(p);ch[x][0]=ch[x][1]=0;size[x]=1;}void init(){pow[0]=1;for(int i=1;i<=len;i++)pow[i]=pow[i-1]*seed;root=n+1,size[n+1]=2,ch[n+1][1]=n+2;size[n+2]=1,fa[n+2]=n+1;val[n+1]=0,val[n+2]=(1ll<<64)-1;}int main(){int m,i,j,k,a,b,x,y;scanf("%d%d%d",&n,&len,&m);init();for(i=1;i<=n;i++){scanf("%s",str[i]+1);for(j=1;j<=len;j++)val[i]=val[i]*seed+str[i][j];Insert(i);}for(i=1;i<=m;i++){scanf("%d%d%d%d",&x,&a,&y,&b);if(x==y){del(x);swap(str[x][a],str[x][b]);for(j=1,val[x]=0;j<=len;j++)val[x]=val[x]*seed+str[x][j];Insert(x);continue;}del(x),del(y);swap(str[x][a],str[y][b]);for(j=1,val[x]=val[y]=0;j<=len;j++)val[x]=val[x]*seed+str[x][j],val[y]=val[y]*seed+str[y][j];Insert(x),Insert(y);}Down(root);for(i=1;i<=n;i++)printf("%d\n",ans[i]);return 0;}



0 0