【BZOJ 1014】[JSOI2008]火星人prefix hash+splay+二分

来源:互联网 发布:轻而易举的软件多少钱 编辑:程序博客网 时间:2024/04/30 02:00

一开始以为会是后缀数组之类的什么鬼东西,结果最后想了半天没想出来,结果想到hash秒出答案,所以有的时候应该考虑换一下思维方式。

因为题目要求查询和修改操作,维护一个splay,每个节点对应这个位置的字符和这棵子树的hash值,就能完成插入修改操作了,每一个询问的时候再二分最长前缀hash cheak就好了

然后。。。有一个函数忘了写return值结果BZOJ一直说我T,我改了很多常数还是T,最后才发现就过了郁闷

#include<cstdio>#include<cstring>#include<iostream>#define maxn 200020#define ls ch[u][0]#define rs ch[u][1]#define uint unsigned intusing namespace std;int ch[maxn][2],val[maxn],fa[maxn],size[maxn],rt,tot,len;uint pw[maxn],h[maxn]; void init(int u){    size[u]=size[ls]+size[rs]+1;    h[u]=(h[ls]*pw[size[rs]+1]+val[u]*pw[size[rs]]+h[rs]);}void Rotate(int u){    int d=u==ch[fa[u]][0];    int f=fa[u],ff=fa[f];    fa[u]=ff;if(ff!=0)ch[ff][f==ch[ff][1]]=u;    ch[f][!d]=ch[u][d];fa[ch[u][d]]=f;    ch[u][d]=f;fa[f]=u;    init(f);init(u);}void splay(int u,int k=0){    if(u==0)return;    while(fa[u]!=k){        int f=fa[u],ff=fa[f];        if(ff==k){Rotate(u);break;}        int d=u==ch[f][1],dd=f==ch[ff][1];        if(d==dd)Rotate(f);        else Rotate(u);        Rotate(u);    }    if(k==0)rt=u;}//插入一个符号是x 排在第k的字符 void insert(int u,int f,int x,int k,int d){    if(u==0){        tot++;        val[tot]=h[tot]=x,fa[tot]=f,size[tot]=1,ch[f][d]=tot;        splay(tot);        return;    }    if(k>size[ls]+1)insert(rs,u,x,k-size[ls]-1,1);    else insert(ls,u,x,k,0);}void change(int u,int k,int x){    if(k==size[ls]+1){        splay(u);val[u]=x;        init(u);        return;    }    if(k>size[ls]+1)change(rs,k-size[ls]-1,x);    else change(ls,k,x);}//找k的前缀和 uint query(int u,int k){    if(k==0)return 0;    if(k==size[ls]+1){        splay(u);        return h[ls]*pw[1]+val[u];    }    if(k>size[ls]+1)return query(rs,k-size[ls]-1);    return query(ls,k);}uint find(int a,int b){    if(b==0)return 0;    if(a+b-1>len)return -a;    return query(rt,a+b-1)-query(rt,a-1)*pw[b];} int solve(int a,int b){    int l=0,r=min(len-a,len-b)+1,ans;    while(l<=r){        int mid=l+r>>1;        if(find(a,mid)==find(b,mid))ans=mid,l=mid+1;        else r=mid-1;    }    return ans;}char s[maxn],c[5];int build(int l,int r,int f){    if(l>r)return 0;    tot++;    int u=tot;    if(l==r){        h[u]=val[u]=s[l]-'a',fa[u]=f,size[u]=1;        return u;    }    int mid=l+r>>1;    val[u]=s[mid]-'a',fa[u]=f;    ch[u][0]=build(l,mid-1,u);    ch[u][1]=build(mid+1,r,u);    init(u);    return u;} int main(){    pw[0]=1;    for(int i=1;i<=200000;i++)pw[i]=pw[i-1]*233;    scanf("%s",s+1);len=strlen(s+1);int a,b,n;    rt=build(1,len,0);    scanf("%d",&n);    while(n--){        scanf("%s",c);        if(c[0]=='Q'){            scanf("%d%d",&a,&b);            printf("%d\n",solve(a,b));        }else if(c[0]=='R'){            scanf("%d%s",&a,c);            change(rt,a,c[0]-'a');        }else {            scanf("%d%s",&a,c);            insert(rt,0,c[0]-'a',a+1,a+1>size[ch[rt][0]]+1);            len++;        }    }    return 0;}


0 0
原创粉丝点击