bzoj1014火星人

...强迫症终于A了这道题  bzoj前30道全A指日可待

splay维护这个结点控制的字符串的hash值

每次旋转重新算一遍就可以了

查询的时候跑一个二分

讲起来很简单但是还是调了1h才调对了splay

把main写完饺子都凉了

没写过几次平衡树 常数写的奇大 能递归的我都递归了。。。

字符串哈希因为过于Naive只会用自然溢出。。。

但是1A了

家里的电脑有写好的read和write

我竟然忘了。。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#define ll unsigned long long
#define pi 3.14
#define eps 1e-9
#define inf 2147483233
#define m(a) memset(a,0,sizeof(a))
#define M(a) memset(a,127,sizeof(a))
#define REP(i,m,n) for(int i=1;i<=n;i++)
#define DWN(i,n,m) for(int i=n;i>=1;i++)
#define lowbit(x) x&(-x)
using namespace std;
int n;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=10*x+ch-'0';ch=getchar();}
    return x*f;
}
inline void write(int x)
{
    int num=0;
    char buf[15];
    while(x)buf[++num]=(x%10)+'0',x/=10;
    while(num)putchar(buf[num--]);
    putchar('\n');
}
ll powe[150000];
void makepow()
{
    int i;
    for(powe[0]=1,i=1;i<140142;i++)powe[i]=powe[i-1]*131;
}
const int maxn=140142;
char str[maxn];
struct SplayTree
{
    int rt,Size;
    int son[maxn][2],f[maxn],size[maxn];
    ll val[maxn],hsh[maxn];
    char s[maxn];
    inline void pushup(int x){size[x]=size[son[x][0]]+size[son[x][1]]+1;hsh[x]=hsh[son[x][0]]+powe[size[son[x][0]]]*s[x]+powe[size[son[x][0]]+1]*hsh[son[x][1]];}
    inline void Rotate(int x,int type)
    {
        int y=f[x];
        son[y][!type]=son[x][type];
        f[son[x][type]]=y;
        f[x]=f[y];
        if(f[x])son[f[y]][son[f[y]][1]==y]=x;  
        son[x][type]=y;
        f[y]=x;
        size[x]=size[y],hsh[x]=hsh[y];
        pushup(y);
    }
    inline void splay(int x,int goal)
    {
        while(f[x]!=goal)  
        {  
            if(f[f[x]]==goal)  
            {  
                if(son[f[x]][0]==x)Rotate(x,1);  
                else Rotate(x,0);  
            }  
            else  
            {  
               int y=f[x],z=f[y];  
               if(son[z][0]==y)  
               {  
                  if(son[y][0]==x)Rotate(y,1),Rotate(x,1);  
                  else Rotate(x,0),Rotate(x,1);  
               }  
               else  
               {  
                   if(son[y][1]==x)Rotate(y,0),Rotate(x,0);  
                   else Rotate(x,1),Rotate(x,0);  
               }  
            }  
        }  
        if(goal==0) rt=x;
    }
    inline int rank(int x,int k)
    {
        if(k<=size[son[x][0]]) return rank(son[x][0],k);  
        else if(k==size[son[x][0]]+1) return x;  
        else return rank(son[x][1],k-size[son[x][0]]-1); 
    }
    inline int build(int l,int r,int id)
    {
        if(l>r)return 0;
        int x=++Size,mid=(l+r)>>1;
        f[x]=id;
        s[x]=str[mid];
        son[x][0]=build(l,mid-1,x);  
        son[x][1]=build(mid+1,r,x);  
        pushup(x);  
        return x;
    }
    inline void insert(int k,char val)  
    {  
        int x=rank(rt,k),y=rank(rt,k+1);  
        splay(x,0),splay(y,x);  
        s[++Size]=val;  
        f[Size]=y,son[y][0]=Size;  
        pushup(Size);  
        pushup(y);  
        pushup(x);  
    }
    inline void change(int k,int val)
    {
        int x=rank(rt,k);  
        splay(x,0);  
        s[x]=val;  
        pushup(x);
    }
    inline int bisearch(int kx,int ky)
    {  
        int l=0,r=n,mid;  
        while(l<=r)  
        {  
            mid=l+r>>1;  
            if(ky+mid>n+2)  
            {  
                r=mid-1;  
                continue;  
            }  
            int x=rank(rt,kx-1),y=rank(rt,kx+mid);  
            splay(x,0),splay(y,x);  
            ll temp=hsh[son[y][0]];  
            x=rank(rt,ky-1),y=rank(rt,ky+mid);  
            splay(x,0),splay(y,x);  
            if(temp==hsh[son[y][0]])l=mid+1;  
            else r=mid-1;  
        }  
        return r;  
    }  
}splay;
int main()
{
    int m,i,j,k,x,y;
    char op[10],val[10];
    scanf("%s%d",str+1,&m);  
    makepow();
    n=strlen(str+1);
    splay.rt=splay.build(0,n+1,0);  
    for(i=1;i<=m;i++)  
    {  
        scanf("%s",op);  
        if(op[0]=='I')  
        {  
            scanf("%d%s",&x,val);  
            splay.insert(x+1,val[0]);  
            n++;  
        }  
        else if(op[0]=='R')  
        {  
            scanf("%d%s",&x,val);  
            splay.change(x+1,val[0]);  
        }  
        else  
        {  
            scanf("%d%d",&x,&y);  
            if(x>y)  swap(x,y);  
            if(x!=y)  
                printf("%d\n",splay.bisearch(x+1,y+1));  
            else  
                printf("%d\n",n-x+1);  
        }  
    }  
    return 0;  
}
View Code

 

转载于:https://www.cnblogs.com/Kong-Ruo/p/7895957.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值