BZOJ1014 [JSOI2008]火星人prefix

Posted 大奕哥&VANE

tags:

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

我们可以使用二分答案来计算。

至于添加和修改操作我们可以使用Splay来维护复杂度O(mlogn)当然Splay常数很大。

BZOJ上长时间TLE,有dalao可以帮忙看看,luogu上能过。

#include<bits/stdc++.h>
using namespace std;
const int N=150005,mod=9875321;
typedef long long ll;
int size[N],fa[N],c[N][2],v[N],h[N],p[N],n,m,cnt,rt;
char ch[N];
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
void update(int x)
{
    size[x]=size[c[x][0]]+size[c[x][1]]+1;
    h[x]=(h[c[x][0]]+1ll*v[x]*p[size[c[x][0]]]%mod+1ll*h[c[x][1]]*p[size[c[x][0]]+1]%mod)%mod;
}
void rotate(int x,int &k)
{
    int y=fa[x],z=fa[y],l,r;
    l=(c[y][1]==x);r=l^1;
    if(k==y)k=x;else c[z][c[z][1]==y]=x;
    fa[y]=x;fa[x]=z;fa[c[x][r]]=y;
    c[y][l]=c[x][r];c[x][r]=y;
    update(y);update(x);
}
void splay(int x,int &k)
{
    while(x!=k)
    {
        int y=fa[x],z=fa[y];
        if(y!=k)
        {
            if(c[y][0]==x^c[z][0]==y)rotate(x,k);
            else rotate(y,k);
        }
        rotate(x,k);
    }
}
int find(int x,int k)
{
    if(size[c[x][0]]+1==k)return x;
    else if(size[c[x][0]]>=k)return find(c[x][0],k);
    else return find(c[x][1],k-size[c[x][0]]-1);
}
void insert(int k,int w)
{
    int x=find(rt,k),y=find(rt,k+1);
    splay(x,rt);splay(y,c[x][1]);
    int z=++cnt;c[y][0]=z;fa[z]=y;v[z]=w;
    update(z);update(y);update(x);
}
int query(int k,int w)
{
    int x=find(rt,k);int y=find(rt,k+w+1);
    splay(x,rt);splay(y,c[x][1]);
    int z=c[y][0];
    return h[z];
}
int solve(int x,int y)
{
    int l=1,r=min(cnt-x,cnt-y)-1,ans=0;
    while(l<=r)
    {
        int mid=l+r>>1;
        if(query(x,mid)==query(y,mid))l=mid+1,ans=mid;
        else r=mid-1;
    }
    return ans;
}
void build(int l,int r,int f)
{
    if(l>r)return;
    int mid=l+r>>1;
    fa[mid]=f;c[f][mid>=f]=mid;v[mid]=ch[mid]-a+1;
    if(l==r){
        size[mid]=1;h[mid]=v[mid];return;
    }
    build(l,mid-1,mid);build(mid+1,r,mid);
    update(mid);
}
int main()
{
    scanf("%s",ch+2);
    n=strlen(ch+2);int x,y;
    p[0]=1;for(int i=1;i<=150004;++i)p[i]=p[i-1]*27%mod;cnt=n+2;
    build(1,n+2,0);rt=(n+3)>>1;
    m=read();char s[5],d[5];
    for(int i=1;i<=m;++i)
    {
        scanf("%s",s);
        if(s[0]==Q){
            x=read();y=read();printf("%d\n",solve(x,y));
        }
        else if(s[0]==R){
            x=read();scanf("%s",d+1);x=find(rt,x+1);splay(x,rt);
            v[rt]=d[1]-a+1;update(rt);
        }
        else{
            x=read();scanf("%s",d+1);insert(x+1,d[1]-a+1);
        }
    }
    return 0;
}

 

以上是关于BZOJ1014 [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