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+二分