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\n",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;   
}

 

posted on 2014-03-09 22:45  BLADEVIL  阅读(263)  评论(0编辑  收藏  举报