• BZOJ 1014 [JSOI2008]火星人prefix | Splay维护哈希值


    题目:


    题解:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    typedef long long ll;
    #define N 100010
    #define Base 29
    #define which(x) (ls[fa[(x)]]==(x))
    using namespace std;
    int n,m,idx,root,fa[N],ls[N],rs[N],val[N],sz[N],a,b;
    ll hsh[N],pw[N];
    char s[N],op[10];
    void upt(int u)
    {
        sz[u]=sz[ls[u]]+sz[rs[u]]+1;
        hsh[u]=hsh[ls[u]]+val[u]*pw[sz[ls[u]]]+hsh[rs[u]]*pw[sz[ls[u]]+1];
    }
    void rotate(int u)
    {
        int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u];
        if (w) which(v)?ls[w]=u:rs[w]=u;
        which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v);
        fa[u]=w,fa[v]=u;
        if (b) fa[b]=v;
        upt(v),upt(u);
    }
    void splay(int u,int tar)
    {
        while (fa[u]!=tar)
        {
        if (fa[fa[u]]!=tar)
            (which(u)==which(fa[u]))?rotate(fa[u]):rotate(u);
        rotate(u);
        }
        if (!tar) root=u;
    }
    int build(int l,int r,int pre)
    {
        if (l>r) return 0;
        int u=++idx,mid=l+r>>1;
        val[u]=s[mid]-'a'+1,fa[u]=pre;
        ls[u]=build(l,mid-1,u);
        rs[u]=build(mid+1,r,u);
        upt(u);
        return u;
    }
    int find(int x)
    {
        int u=root;
        while(sz[ls[u]]!=x)
        if (x<=sz[ls[u]]-1) u=ls[u];
        else x-=sz[ls[u]]+1,u=rs[u];
        return u;
    }
    void insert(int pos,int x)
    {
        int u=find(pos),v=find(pos+1);
        splay(u,0),splay(v,u);
        ls[v]=++idx,fa[idx]=v,val[idx]=x,sz[idx]=1;
        splay(idx,0);
    }
    void change(int pos,int x)
    {
        int u=find(pos);
        val[u]=x;
        splay(u,0);
    }
    ll gethsh(int pos,int len)
    {
        int u=find(pos-1),v=find(pos+len);
        splay(u,0),splay(v,u);
        return hsh[ls[v]];
    }
    int query(int a,int b)
    {
        int l=0,r=sz[root]-max(a,b)-1,mid;
        while (l<r)
        {
        mid=l+r+1>>1;
        if (gethsh(a,mid)==gethsh(b,mid)) l=mid;
        else r=mid-1;
        }
        return l;
    }
    int main()
    {
        scanf("%s",s+1);
        n=strlen(s+1);
        pw[0]=1;
        for (int i=1;i<N;i++)
        pw[i]=pw[i-1]*Base;
        root=build(0,n+1,0);
        scanf("%d",&m);
        while (m--)
        {
        scanf("%s",op);
        if (op[0]=='Q')
        {
            scanf("%d%d",&a,&b);
            printf("%d
    ",query(a,b));
        }
        else if (op[0]=='I')
        {
            int pos;
            scanf("%d%s",&pos,op);
            insert(pos,op[0]-'a'+1);
        }
        else if (op[0]=='R')
        {
            int pos;
            scanf("%d%s",&pos,op);
            change(pos,op[0]-'a'+1);
        }
        }
        return 0;
    }
  • 相关阅读:
    2015/5/10站立会议(补发)
    2015/5/11站立会议(补发)
    2015/5/12站立会议(补发)
    5/13站立会议(补发)
    面向对象——抽象类和接口
    面向对象(三)——静态
    面向对象——三大特性(封装、继承、多态)
    ADO.NET
    面向对象 封装练习题
    面向对象 封装
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8137022.html
Copyright © 2020-2023  润新知