首页 > 代码库 > 【bzoj1014】: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分

【bzoj1014】: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分

【bzoj1014】: [JSOI2008]火星人

用平衡树维护字符串的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 }
View Code

并不会splay。。只会非旋转treap。。10s正好卡过去。。药丸

【bzoj1014】: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分