Hash_1014: [JSOI2008]火星人prefix

时间:2021-05-11 06:12:56
 #include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef unsigned int ll;
#define maxn 150005
#define p 53
int n,m,root,tot,fa[maxn],son[maxn][],size[maxn];
ll val[maxn],sum[maxn],bin[maxn];
char st[maxn],op[];
void read(int &x){
x=; int f=; char ch;
for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') f=-;
for (;isdigit(ch);ch=getchar()) x=x*+ch-''; x*=f;
}
struct SPLAY{
int which(int x){
return son[fa[x]][]==x;
}
void updata(int x){
int ls=son[x][],rs=son[x][];
size[x]=size[ls]+size[rs]+;
sum[x]=sum[rs]+val[x]*bin[size[rs]]+sum[ls]*bin[+size[rs]];
}
int build(int l,int r){
int x; if (l>r) return ; int mid=(l+r)>>;
if (mid==) x=n+,val[x]=;
else if (mid==n+) x=n+,val[x]=;
else x=mid,val[x]=st[x]-'a'; size[x]=;
son[x][]=build(l,mid-),son[x][]=build(mid+,r),updata(x);
if (son[x][]) fa[son[x][]]=x;
if (son[x][]) fa[son[x][]]=x;
return x;
}
void rotata(int x){
int y=fa[x],d=which(x),dd=which(y);
if (fa[y]) son[fa[y]][dd]=x; fa[x]=fa[y];
fa[son[x][d^]]=y,son[y][d]=son[x][d^];
fa[y]=x,son[x][d^]=y,updata(y);
}
void splay(int x,int goal){
while (fa[x]!=goal){
if (fa[fa[x]]==goal) rotata(x);
else if (which(x)==which(fa[x])) rotata(fa[x]),rotata(x);
else rotata(x),rotata(x);
}
if (goal==) root=x; updata(x);
}
int kth(int x){
int y=root,ls,rs; if (!root) return ;
for (;;){
ls=son[y][],rs=son[y][];
if (size[ls]+==x) return y;
else if (size[ls]>=x) y=ls;
else x-=size[ls]+,y=rs;
}
}
bool check(int x,int y,int len){
int t1,t2; t1=kth(x),t2=kth(x+len+);
ll z;splay(t1,),splay(t2,t1),z=sum[son[t2][]];
t1=kth(y),t2=kth(y+len+); splay(t1,),splay(t2,t1);
return z==sum[son[t2][]];
}
}Splay;
void query(int x,int y){
int l=,r,mid,ans=; r=min(tot--x+,tot--y+);
while (l<=r){
mid=(l+r)>>;
if (Splay.check(x,y,mid)==) ans=mid,l=mid+;
else r=mid-;
}printf("%d\n",ans);
}
int main(){
bin[]=; for (int i=;i<=;i++) bin[i]=bin[i-]*p;
scanf("%s",st+),n=strlen(st+);
root=Splay.build(,n+); tot=n+;
read(m);
for (int x,y;m;m--){
scanf("%s",op+);
if (op[]=='Q') read(x),read(y),query(x,y);
else if (op[]=='R') read(x),scanf("%s",op+),x=Splay.kth(x+),Splay.splay(x,),val[x]=op[]-'a',Splay.updata(x);
else{
read(x),scanf("%s",op+),++tot,val[tot]=op[]-'a',size[tot]=;
int t1=Splay.kth(x+),t2=Splay.kth(x+); Splay.splay(t1,),Splay.splay(t2,t1);
fa[tot]=t2,son[t2][]=tot,Splay.updata(t2),Splay.splay(tot,);
}
}
return ;
}

Splay维护,询问时二分答案,Hash判定,我用的是53进制。

splay,二分,Hash。