BZOJ 1014 [JSOI2008]火星人prefix

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1014 [JSOI2008]火星人prefix相关的知识,希望对你有一定的参考价值。

splay维护hash值;

看到大佬们都在打数据结构,我说好的不打数据结构又自己打脸了。

为了写这个昨天还特意去打了Splay的普通平衡树,自从我学会Treap以来第一次用splayA掉普通平衡树QAQ

没有在前后加点,所以特判了在前后加字母的情况。查询就二分答案,然后转过去取hash值,判断是否相等。

一开始用了mod 1e9+7,狂T不止,到处翻别人的博客听说用unsigned long long 自然溢出很快,改后就快了一倍。。

技术分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#define lc ch[x][0]
#define rc ch[x][1]
typedef unsigned long long LL;
const int maxn=300000+299;
using namespace std;
int len,root,tot,T,x,y,sz[maxn],ch[maxn][2],p[maxn];
LL v[maxn],ha[maxn],base=131,power[maxn];
char s[maxn],op[10],c[10];
inline int read() {
    char ch=getchar(); int f=1,ret=0;
    while(ch!=-&&(ch>9||ch<0)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) ret=ret*10+ch-0;
    return ret*f;
}
void update(int x) {
    sz[x]=sz[lc]+sz[rc]+1;
    ha[x]=(ha[lc]*power[sz[rc]+1]+v[x]*(power[sz[rc]])+ha[rc]);
}
void rotate(int x) {
    int y=p[x],z=p[y],l=(x==ch[y][1]),r=l^1;
    if(z) ch[z][y==ch[z][1]]=x; p[x]=z;
    ch[y][l]=ch[x][r]; p[ch[x][r]]=y;
    ch[x][r]=y; p[y]=x;
    update(y); update(x);
}
void splay(int x,int FA) {
    if(p[x]==FA) return;
    for(;p[x]!=FA;rotate(x)) {
        int y=p[x],z=p[y];
        if(z!=FA) (y==ch[z][1])^(x==ch[y][1])?rotate(x):rotate(y);
    }
    if(!FA) root=x;
}
int build(int l,int r) {
    int x=++tot;
    sz[x]==1;
    int mid=(l+r)>>1;
    v[x]=s[mid-1];
    if(mid-1>=l) lc=build(l,mid-1);
    if(mid+1<=r) rc=build(mid+1,r);
    if(lc) p[lc]=x;
    if(rc) p[rc]=x;
    update(x);
    return x;
}
int kth(int k) {
    int res=-1;
    for(int x=root;x;) {
        if(sz[lc]+1==k) return x;
        if(sz[lc]+1>k) x=lc;
        else k-=(sz[lc]+1),x=rc;
    }
}
LL find(int l,int r) {
    int ll=kth(l),rr=kth(r);
    if(ll==rr) return v[ll];
    splay(ll,0);
    splay(rr,ll);
    LL res=v[root]*power[sz[ch[ch[root][1]][0]]+1]+ha[ch[ch[root][1]][0]]*power[1]+v[ch[root][1]];
    return res;
}
int ef(int x,int y) {
    int res=0;
    if(x>y) swap(x,y);
    if(x==y) return sz[root]-y+1;
    int l=0,r=sz[root]-y;
    while(l<=r) {
        int mid=(l+r)>>1;
        if(find(x,x+mid)==find(y,y+mid)) res=mid+1,l=mid+1;
        else r=mid-1;
    }
    return res;
}
int main()
{
    scanf("%s",s);
    len=strlen(s); 
    power[0]=1;
    for(int i=1;i<=maxn-290;i++) power[i]=power[i-1]*base;
    root=build(1,len);
    T=read();
    while(T--) {
        scanf("%s",op);
        if(op[0]==Q) {
            scanf("%d%d",&x,&y);
            printf("%d\n",ef(x,y));
        }
        else if(op[0]==R) {
            scanf("%d%s",&x,c);
            int ll=kth(x);
            splay(ll,0);
            v[root]=c[0];
            update(root);
        }
        else {
            scanf("%d%s",&x,c);
            if(x==0) {
                int ll=kth(1);
                splay(ll,0);
                ch[root][0]=++tot;
                sz[tot]=1; p[tot]=root;
                v[tot]=ha[tot]=c[0];
                update(root);
            }
            else {
                int ll=kth(x);
                splay(ll,0);
                if(x==sz[root]) {
                    ch[root][1]=++tot;
                    sz[tot]=1; p[tot]=root;
                    v[tot]=ha[tot]=c[0];
                    update(root);
                }
                else {
                    int ll=kth(x);
                    splay(ll,0);
                    int rr=kth(x+1);
                    splay(rr,ll);
                    ch[rr][0]=++tot;
                    sz[tot]=1; p[tot]=rr;
                    v[tot]=ha[tot]=c[0];
                    update(rr);
                    update(root);
                }
            }
        }
    }
    return 0;
}
View Code

 

以上是关于BZOJ 1014 [JSOI2008]火星人prefix的主要内容,如果未能解决你的问题,请参考以下文章

[BZOJ1014][JSOI2008]火星人prefix

BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)

[BZOJ1014][JSOI2008]火星人prefix splay+二分+hash

[BZOJ]1014 火星人prefix(JSOI2008)

bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix

BZOJ1014 [JSOI2008]火星人prefix