bzoj 1014 火星人
比较字符串?不好处理?我们想到用哈希来比较。
每个节点记录它包括它的子树所表示的字符串的哈希值,这样我们可以通过二分长度,旋转出区间来判定。
对于哈希值我们不必取特定的模数,只要让它乘爆就行,int就是模数。
过程想清楚了就很好写了。
prefix
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 240000 7 #define inf 2147483647 8 #define ms 2147483647 9 using namespace std; 10 int c[maxn][2]; 11 int fa[maxn],size[maxn],key[maxn],hx[maxn],po[maxn]; 12 int n,m,num,rot; 13 14 inline void update(int x) 15 { 16 if (!x) return ; 17 hx[x]=(hx[c[x][0]]+(key[x]+hx[c[x][1]]*27)*po[size[c[x][0]]]); 18 size[x]=size[c[x][0]]+size[c[x][1]]+1; 19 } 20 21 inline void rotate(int x,int &rot) 22 { 23 int y=fa[x],z=fa[y]; 24 int p=(c[y][1]==x),q=p^1; 25 if (y==rot) rot=x; 26 else if (c[z][0]==y) c[z][0]=x; else c[z][1]=x; 27 fa[x]=z; fa[y]=x; fa[c[x][q]]=y; 28 c[y][p]=c[x][q]; c[x][q]=y; 29 update(y); 30 } 31 32 inline void splay(int x,int &rot) 33 { 34 while (x!=rot) 35 { 36 int y=fa[x],z=fa[y]; 37 if (y!=rot) 38 if ((c[z][0]==y)xor(c[y][0]==x)) rotate(x,rot); else rotate(y,rot); 39 rotate(x,rot); 40 } 41 update(x); 42 } 43 44 inline int build(int l,int r) 45 { 46 int mid=(l+r)>>1,left=0,right=0; 47 if (l<mid) left=build(l,mid-1); 48 if (r>mid) right=build(mid+1,r); 49 c[mid][0]=left; c[mid][1]=right; 50 fa[left]=fa[right]=mid; 51 update(mid); 52 return mid; 53 } 54 55 inline int find(int t,int k) 56 { 57 if (k==size[c[t][0]]+1) return t; 58 if (k<size[c[t][0]]+1) return find(c[t][0],k); 59 if (k>size[c[t][0]]+1) return find(c[t][1],k-size[c[t][0]]-1); 60 } 61 62 inline bool judge(int x,int y,int len) 63 { 64 if (len==1) return key[find(rot,x+1)]==key[find(rot,y+1)]; 65 int ll=find(rot,x),rr=find(rot,x+len+1); 66 splay(rr,rot); splay(ll,c[rot][0]); 67 int a1=hx[c[ll][1]]; 68 69 ll=find(rot,y),rr=find(rot,y+len+1); 70 splay(rr,rot); splay(ll,c[rot][0]); 71 int a2=hx[c[ll][1]]; 72 return a1==a2; 73 } 74 75 int main() 76 { 77 freopen("prefix.in","r",stdin); 78 char s[maxn]; 79 scanf("%s",&s); 80 num=strlen(s); 81 po[0]=1; 82 for (int i=1;i<=maxn;i++) po[i]=po[i-1]*27; 83 key[1]=0; 84 for (int i=1;i<=num;i++) key[i+1]=s[i-1]-'a'+1; 85 key[num+2]=0;num+=2; 86 rot=build(1,num); 87 //for (int i=1;i<=num;i++) cout<<key[i]<<' '; 88 //cout<<endl; 89 //for (int i=1;i<=num;i++) cout<<i<<' '<<fa[i]<<' '<<c[i][0]<<' '<<c[i][1]<<' '<<size[i]<<' '<<key[i]<<' '<<hx[i]<<endl; 90 scanf("%d\n",&n); 91 char sign,z; 92 int x,y; 93 for (int i=1;i<=n;i++) 94 { 95 scanf("%c",&sign); 96 if (sign=='Q') 97 { 98 scanf("%d %d\n",&x,&y); 99 if (x>y) swap(x,y); 100 int l=1,r=num-1-y,ans=0; 101 while (l<=r) 102 { 103 int mid=(l+r)>>1; 104 if (judge(x,y,mid)) l=mid+1,ans=mid; 105 else r=mid-1; 106 } 107 printf("%d\n",ans); 108 } 109 if (sign=='R') 110 { 111 scanf("%d %c\n",&x,&z); 112 int t=find(rot,x+1); 113 key[t]=z-'a'+1; 114 splay(t,rot); 115 } 116 if (sign=='I') 117 { 118 scanf("%d %c\n",&x,&z); 119 int ll=find(rot,x+1),rr=find(rot,x+2); 120 splay(rr,rot); splay(ll,c[rot][0]); 121 key[++num]=z-'a'+1; 122 c[ll][1]=num; fa[num]=ll; 123 splay(num,rot); 124 } 125 } 126 return 0; 127 }
AC without art, no better than WA !