bzoj1014: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分
Posted karl07
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1014: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分相关的知识,希望对你有一定的参考价值。
用平衡树维护字符串的hash
然后询问的时候二分一下就好了
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 #define ull unsigned long long 9 10 const int N=1000005; 11 const int P=131; 12 struct tre{ 13 int key,sz,t; 14 ull hash; 15 tre *ls,*rs; 16 }t[N*3],*NEW=t,*null=t,*root,*r1,*r2,*r3; 17 ull base[N]; 18 char s[N]; 19 int n; 20 21 inline tre *new1(int x){ 22 NEW++; 23 NEW->t=x; 24 NEW->key=rand(); 25 NEW->sz=1; 26 NEW->hash=x; 27 NEW->ls=NEW->rs=null; 28 return NEW; 29 } 30 31 inline void update(tre *p){ 32 p->sz=p->ls->sz+1+p->rs->sz; 33 p->hash=p->ls->hash*base[p->rs->sz+1]+p->t*base[p->rs->sz]+p->rs->hash; 34 } 35 36 void merge(tre *&p,tre *x,tre *y){ 37 if (x==null) { p=y; return; } 38 if (y==null) { p=x; return; } 39 if (x->key>y->key){ 40 p=x; 41 merge(p->rs,p->rs,y); 42 }else{ 43 p=y; 44 merge(p->ls,x,p->ls); 45 } 46 update(p); 47 } 48 49 void split(tre *p,tre *&x,tre *&y,int k){ 50 if (k==0) { x=null,y=p; return; } 51 if (k==p->sz) { y=null,x=p; return; } 52 if (k>=p->ls->sz+1){ 53 x=p; 54 split(p->rs,p->rs,y,k-p->ls->sz-1); 55 }else{ 56 y=p; 57 split(p->ls,x,p->ls,k); 58 } 59 update(p); 60 } 61 62 void HASH(){ 63 null->ls=null->rs=null; 64 null->hash=0; 65 null->sz=null->t=0; 66 null->key=-1; 67 root=null; 68 base[0]=1; 69 for (int i=1;i<N;i++) base[i]=base[i-1]*P; 70 } 71 72 inline ull Q(tre *p,int l,int x){ 73 ull ans; 74 split(root,r1,r2,l-1); 75 split(r2,r2,r3,x); 76 ans=r2->hash; 77 merge(r2,r2,r3); 78 merge(root,r1,r2); 79 return ans; 80 } 81 82 inline void R(int l,int x){ 83 split(root,r1,r2,l-1); 84 split(r2,r2,r3,1); 85 merge(r1,r1,new1(x)); 86 merge(root,r1,r3); 87 } 88 89 inline void I(int l,int x){ 90 split(root,r1,r2,l); 91 merge(r1,r1,new1(x)); 92 merge(root,r1,r2); 93 } 94 95 inline int query(int x,int y){ 96 if (x>y) swap(x,y); 97 int l=0,r=root->sz-y+1,ans=0; 98 while (l<=r){ 99 int mid=(l+r)/2; 100 ull a1=Q(root,x,mid),a2=Q(root,y,mid); 101 if (a1==a2){ 102 ans=mid; 103 l=mid+1; 104 }else{ 105 r=mid-1; 106 } 107 } 108 return ans; 109 } 110 111 int main(){ 112 HASH(); 113 scanf("%s",s); 114 scanf("%d",&n); 115 for (int i=0,l=strlen(s);i<=l-1;i++){ 116 merge(root,root,new1(s[i])); 117 } 118 for (int i=1,x,y;i<=n;i++){ 119 char ss[10],s1[10]; 120 scanf("%s",ss); 121 if (ss[0]==\'Q\') { scanf("%d%d",&x,&y); printf("%d\\n",query(x,y)); } 122 if (ss[0]==\'R\') { scanf("%d%s",&x,s1); R(x,s1[0]);} 123 if (ss[0]==\'I\') { scanf("%d%s",&x,s1); I(x,s1[0]);} 124 } 125 return 0; 126 }
并不会splay。。只会非旋转treap。。10s正好卡过去。。药丸
以上是关于bzoj1014: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)
[BZOJ1014][JSOI2008]火星人prefix splay+二分+hash
[BZOJ]1014 火星人prefix(JSOI2008)