• bzoj 2258 splay


      类似于1014,用splay维护这个序列,维护每个节点为根的子树的hash值,对于一个询问二分答案判断就行了。

      反思:询问的时候因为是原序列的x,y,所以开始的时候直接splay(x-1)了,后来发现这是不对的,因为可能在x前插入一些东西,所以需要麻烦些,先splay(x),然后提出来右端点为size[son[rot][0]]+1+len,然后再splay(find(size[son[rot][0]]+1))。

    /**************************************************************
        Problem: 2258
        User: BLADEVIL
        Language: C++
        Result: Accepted
        Time:7904 ms
        Memory:3640 kb
    ****************************************************************/
     
    //By BLADEVIL
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define maxn 100010
     
    using namespace std;
     
    char s[maxn];
    int fac[maxn],key[maxn],num,rot,son[maxn][2],father[maxn],size[maxn],hash[maxn];
     
    void update(int x) {
        if (!x) return ;
        hash[x]=hash[son[x][0]]+(key[x]+hash[son[x][1]]*27)*fac[size[son[x][0]]];
        size[x]=size[son[x][0]]+size[son[x][1]]+1;
    }
     
    int build(int l,int r) {
        int mid=l+r>>1,left=0,right=0;
        if (mid<r) right=build(mid+1,r);
        if (mid>l) left=build(l,mid-1);
        father[left]=father[right]=mid;
        son[mid][0]=left; son[mid][1]=right;
        update(mid);
        return mid;
    }
     
    void rotate(int x,int &rot) {
        int y=father[x],z=father[y];
        int p=(son[y][1]==x),q=p^1;
        if (y==rot) rot=x; else if (son[z][0]==y) son[z][0]=x; else son[z][1]=x;
        father[x]=z; father[y]=x; father[son[x][q]]=y;
        son[y][p]=son[x][q]; son[x][q]=y;
        update(y);
    }
     
    void splay(int x,int &rot) {
        while (x!=rot) {
            int y=father[x],z=father[y];
            if (y!=rot)
                if ((son[y][0]==x)^(son[z][0]==y)) rotate(x,rot); else rotate(y,rot);
            rotate(x,rot);
        }
        update(x);
    }
     
    int find(int x) {
        int t=rot;
        while (1) {
            if (size[son[t][0]]+1==x) return t; else
            if (size[son[t][0]]+1>x) t=son[t][0]; else
            if (size[son[t][0]]+1<x) x-=size[son[t][0]]+1,t=son[t][1];
        }
    }
     
    bool judge(int x,int y,int len) {
        if (len==1) return key[x+1]==key[y+1];
        int p=x+1; splay(p,rot);
        int q=find(size[son[rot][0]]+1+len);
        splay(find(size[son[rot][0]]),rot); splay(q,son[rot][1]);
        int a1=hash[son[q][0]];
        p=y+1; splay(p,rot);
        q=find(size[son[rot][0]]+1+len);
        splay(find(size[son[rot][0]]),rot); splay(q,son[rot][1]);
        int a2=hash[son[q][0]];
        return a1==a2;
    }
     
    int main() {
        scanf("%s",s); num=strlen(s);
        fac[0]=1; for (int i=1;i<maxn;i++) fac[i]=fac[i-1]*27;
        for (int i=2;i<=num+1;i++) key[i]=s[i-2]-'a'+1; num+=2;
        rot=build(1,num);
        int task; scanf("%d",&task);
        while (task--) {
            int x,y;
            scanf("%s",s);
            if (s[0]=='Q') {
                scanf("%d%d",&x,&y);
                if (x>y) swap(x,y);
                splay(y+1,rot);
                int l=1,r=size[son[rot][1]],mid,ans=0;
                while (l<=r) {
                    mid=l+r>>1;
                    if (judge(x,y,mid)) ans=mid, l=mid+1; else r=mid-1;
                }
                printf("%d
    ",ans);
            } else
            if (s[0]=='I') {
                scanf("%s%d",s,&x);
                x=(x>num-2)?num:x;
                key[++num]=s[0]-'a'+1;
                int p=find(x); splay(p,rot);
                int q=find(x+1); splay(q,son[rot][1]);
                father[num]=q; son[q][0]=num;
                splay(num,rot);
            }
        }
        return 0;   
    }
  • 相关阅读:
    每周一荐:代码编辑器sublime
    每周一荐:Google的序列化框架Protobuf
    每周一荐:ObjectiveC的开源开发环境GNUstep
    每周一荐:用gnuplot绘制函数曲线
    每周一荐:学习ACE一定要看的书
    临时变量管理器
    每周一荐:TotalCommand的文件夹同步功能
    每周一荐:支持latex的思维导图软件docear
    关于程序员面试的一点想法
    每周一荐:Python Web开发框架Django
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3590833.html
Copyright © 2020-2023  润新知