题意:
给出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); else Rotate(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]; else p=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]; else p=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; }
原文地址:http://blog.csdn.net/ww140142/article/details/48436675