bzoj1014 火星人 (hash+splay+二分答案)

Posted ressed

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1014 火星人 (hash+splay+二分答案)相关的知识,希望对你有一定的参考价值。

求公共前缀的问题可以用hash+二分来解决,但这个是动态的,所以我们用平衡树来维护区间的hash值

复杂度$O(mlog^2n)$

  1 #include<bits/stdc++.h>
  2 #define CLR(a,x) memset(a,x,sizeof(a))
  3 using namespace std;
  4 typedef long long ll;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> pa;
  7 const int maxn=1e5+10,P=131;
  8 const ull RUA=1145141919810ll;
  9 
 10 inline ll rd(){
 11     ll x=0;char c=getchar();int neg=1;
 12     while(c<0||c>9){if(c==-) neg=-1;c=getchar();}
 13     while(c>=0&&c<=9) x=x*10+c-0,c=getchar();
 14     return x*neg;
 15 }
 16 
 17 int ch[maxn][2],pct,fa[maxn],siz[maxn];
 18 char v[maxn],s[maxn];
 19 ull sum[maxn],bin[maxn];
 20 int M,rt;
 21 
 22 inline void print(int x){
 23     if(!x) return;
 24     print(ch[x][0]);
 25     // printf("!%d %d %d %d
",x,ch[x][0],ch[x][1],fa[x]);
 26     print(ch[x][1]);
 27 }
 28 
 29 inline bool isrc(int x){return x==ch[fa[x]][1];}
 30 
 31 inline void update(int x){
 32     siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
 33     sum[x]=(sum[ch[x][0]]*bin[1]+v[x])*bin[siz[ch[x][1]]]+sum[ch[x][1]];
 34 }
 35 
 36 inline void rotate(int x){
 37     int f=fa[x],ff=fa[f];bool b=isrc(x);
 38     if(ff) ch[ff][isrc(f)]=x; fa[x]=ff;
 39     if(ch[x][!b]) fa[ch[x][!b]]=f; ch[f][b]=ch[x][!b];
 40     fa[f]=x;ch[x][!b]=f;
 41     update(f),update(x);
 42 }
 43 
 44 inline void splay(int x,int tar){
 45     while(fa[x]!=tar&&fa[fa[x]]!=tar){
 46         if(isrc(x)==isrc(fa[x])) rotate(fa[x]);
 47         else rotate(x);rotate(x);
 48     }if(fa[x]!=tar) rotate(x);
 49     if(!tar) rt=x;
 50 }
 51 
 52 inline int findkth(int k){
 53     if(k>pct) return 0;
 54     int x=rt;
 55     while(1){
 56         int w=siz[ch[x][0]];
 57         if(k<=w) x=ch[x][0];
 58         else if(k==w+1) return x;
 59         else k-=w+1,x=ch[x][1];
 60     }
 61 }
 62 
 63 inline void insert(int x,char y){
 64     int p=findkth(x+1);
 65     splay(p,0);
 66     int q=findkth(x+2);
 67     splay(q,p);
 68     int n=++pct;
 69     sum[n]=v[n]=y,siz[n]=1;fa[n]=q,ch[q][0]=n;
 70     splay(n,0);
 71 }
 72 
 73 inline void change(int x,char y){
 74     int p=findkth(x+1);
 75     v[p]=y;update(p);
 76     splay(p,0);
 77 }
 78 
 79 inline ull query(int x,int y){
 80     int p=findkth(x);
 81     if(!p) return RUA;
 82     splay(p,0);
 83     int q=findkth(y+2);
 84     if(!q) return RUA;
 85     splay(q,p);
 86     return sum[ch[q][0]];
 87 }
 88 
 89 int main(){
 90     //freopen("","r",stdin);
 91     int i,j,k;
 92     bin[0]=1;for(i=1;i<=1e5;i++) bin[i]=bin[i-1]*P;
 93     ch[rt=1][1]=2;siz[1]=2;
 94     fa[pct=2]=1;siz[2]=1;
 95     scanf("%s",s+1);int len=strlen(s+1);
 96     for(i=1;i<=len;i++){
 97         insert(i-1,s[i]);
 98     }
 99     M=rd();
100     for(i=1;i<=M;i++){
101         char op[5];scanf("%s",op);
102         if(op[0]==Q){
103             int x=rd(),y=rd();
104             int l=1,r=pct-2,ans=0;
105             while(l<=r){
106                 int m=l+r>>1;
107                 ull a=query(x,x+m-1),b=query(y,y+m-1);
108                 if(a==b&&a!=RUA) ans=m,l=m+1;
109                 else r=m-1;
110             }
111             printf("%d
",ans);
112         }else if(op[0]==I){
113             int x=rd();scanf("%s",op);
114             insert(x,op[0]);
115         }else{
116             int x=rd();scanf("%s",op);
117             change(x,op[0]);
118         }
119     }
120     return 0;
121 }

 

以上是关于bzoj1014 火星人 (hash+splay+二分答案)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)

BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)

[BZOJ1014][JSOI2008]火星人prefix splay+二分+hash

[BZOJ1014][JSOI2008]火星人prefix splay+hash+二分

bzoj1014 火星人prefix Splay 字符串Hash

BZOJ-1014 [JSOI2008]火星人prefix (Splay+二分+hash)