您的位置:首页 > 其它

bzoj1014 神奇的平衡树+hash

2017-08-12 21:28 211 查看
哇塞学到了用平衡树存hash值,黄学长的模板用起来就是好耍。

这道题如果没有修改操作的话,二分hash值就可以搞定或者后缀数组什么的,但这道题要修改所以就用平衡树来存hash值就好了,写起来并不难。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define N 150005
#define mod 9875321
#define ll long long
using namespace std;

int c
[2],siz
,sz,fa
,id
,v
,h
,p
,n,rt,m,a,b;
void update(int x){
int l=c[x][0],r=c[x][1];
siz[x]=siz[l]+siz[r]+1;
h[x]=h[l]+(ll)p[siz[l]]*v[x]%mod+(ll)p[siz[l]+1]*h[r]%mod;
h[x]%=mod;
}
void rotate(int x,int &k){
int y=fa[x],z=fa[y],l,r;
if(c[y][0]==x)l=0;else l=1;r=l^1;
if(y==k)k=x;
else c[z][c[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
update(y);update(x);
}

void splay(int x,int &k){
while(x!=k){
int y=fa[x],z=fa[y];
if(y!=k){
if(c[y][0]==x^c[z][0]==y) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int x,int rk){
int l=c[x][0],r=c[x][1];
if(siz[l]+1==rk) return x;
else if(siz[l]>=rk) return find(l,rk);
else return find(r,rk-siz[l]-1);
}
char ch
,s[2],d[2];

void insert(int k,int val){
int x=find(rt,k+1),y=find(rt,k+2);
splay(x,rt);splay(y,c[x][1]);
int z=++sz;c[y][0]=z;
v[z]=h[z]=val;fa[z]=y;
update(z);update(y);update(x);
}

int query(int k,int mid){
int x=find(rt,k),y=find(rt,k+mid+1);
splay(x,rt);splay(y,c[x][1]);
int z=c[y][0];
return h[z];
}
void solv(int x,int y)
{
int l=1,r=min(sz-x,sz-y)-1,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(query(x,mid)==query(y,mid))l=mid+1,ans=mid;
else r=mid-1;
}
printf("%d\n",ans);
}
void build(int l,int r,int f){
if(l>r)return;
int now=id[l],last=id[f];
if(l==r){
v[now]=h[now]=ch[l]-'a'+1;
fa[now]=last;siz[now]=1;
c[last][l>=f]=now;
return;
}
int mid=(l+r)>>1;now=id[mid];
build(l,mid-1,mid);build(mid+1,r,mid);
v[now]=ch[mid]-'a'+1;fa[now]=last;update(now);
c[last][mid>=f]=now;

}
int main(){
scanf("%s",ch+2);p[0]=1;
n=strlen(ch+2);
for(int i=1;i<=n+2;i++)id[i]=i;
for(int i=1;i<N;i++) p[i]=p[i-1]*27%mod;
build(1,n+2,0);sz=n+2;rt=(n+3)>>1;
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%s",s);
if(s[0]=='Q'){
scanf("%d%d",&a,&b);
solv(a,b);
}
if(s[0]=='R'){
scanf("%d%s",&a,d);
int x=find(rt,a+1);splay(x,rt);
v[x]=d[0]-'a'+1;update(x);
}
if(s[0]=='I'){
scanf("%d%s",&a,d);
insert(a,d[0]-'a'+1);
}
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: