• bzoj1014: [JSOI2008]火星人prefix


    题解:splay维护字符串hash,二分找lcp;

    调试了约一天,错误原因是insert后n没有+1;

    写完了这道题,加上前面两道平衡树题目,get新技能:[splay],[字符串hash];

    这题有一个提速的关键:不要mod大素数,直接uLL自然溢出就好,提速很明显;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    typedef unsigned long long LL; 
    const int maxn=151000;
    int cnt=0,root=0,n,m;
    char s[maxn];
    LL pre[maxn];
    struct node{
        int ch[2],siz,key,fa;
        LL hash;
    }e[maxn];
    inline void updata(int x){
        e[x].siz=e[e[x].ch[0]].siz+e[e[x].ch[1]].siz+1;
        e[x].hash=(e[e[x].ch[0]].hash+(LL)e[e[x].ch[1]].hash*pre[e[e[x].ch[0]].siz+1]+(LL)e[x].key*pre[e[e[x].ch[0]].siz]);
    }
    inline void rotate(int x,int d){
        int y=e[x].fa;
        if(!y)return;
        e[x].fa=e[y].fa;e[y].fa=x;e[e[x].ch[d^1]].fa=y;
        e[y].ch[d]=e[x].ch[d^1];e[x].ch[d^1]=y;
        if(e[x].fa)e[e[x].fa].ch[e[e[x].fa].ch[1]==y]=x;
        updata(y);updata(x);
    }
    inline void splay(int x,int S){
        if(!x)return;
        while(e[x].fa!=S){
            if(e[e[x].fa].fa==S)rotate(x,e[e[x].fa].ch[1]==x);
            else {
                int y=e[x].fa;int z=e[y].fa;
                int d=(e[z].ch[1]==y);
                if(e[y].ch[d]==x){rotate(y,d);rotate(x,d);}
                else {rotate(x,d^1);rotate(x,d);}
            }
        }
        if(!S)root=x;
    }
    inline int build(int left,int right,int fa){
        if(left>right)return 0;
        int mid=(left+right)>>1;
        int x=++cnt;e[x].siz=1;e[x].fa=fa;
        if(mid!=0&&mid!=n+1&&mid!=n+2)e[x].key=(s[mid]-'a'+1);
        e[x].ch[0]=build(left,mid-1,x);
        e[x].ch[1]=build(mid+1,right,x);
        updata(x);
        return x;
    }
    inline int find(int k){
        int x=root;
        while(x){
            if(e[e[x].ch[0]].siz+1==k)return x;
            if(k>e[e[x].ch[0]].siz+1)k-=(e[e[x].ch[0]].siz+1),x=e[x].ch[1];
            else x=e[x].ch[0];
        }
        if(x)splay(x,0);
        return x;
    }
    inline LL query(int x,int len){
        int y=x+len+1;
        x=find(x);y=find(y);
        splay(x,0);splay(y,x);
        return e[e[y].ch[0]].hash;
    }
    int main(){
        scanf("%s",s+1);
        n=strlen(s+1);
        pre[0]=1;for(int i=1;i<=150000;i++)pre[i]=(pre[i-1]*27);
        root=build(0,n+1,0);
        scanf("%d",&m);
        char ch;int x,y,k;
        while(m--){
            scanf(" %c",&ch);
            if(ch=='Q'){
                scanf("%d%d",&x,&y);
                if(x>y)swap(x,y);
                int left=0,right=n-y+1,ans=0;
                while(left<=right){
                    int mid=(left+right)>>1;
                    if(query(x,mid)==query(y,mid))left=mid+1,ans=mid;
                    else right=mid-1;
                }
                printf("%d
    ",ans);
                continue;
            }
            if(ch=='R'){
                scanf("%d %c",&x,&ch);
                x=find(x+1);
                splay(x,0);
                e[x].key=ch-'a'+1;
                updata(x);
                continue;
            }
            if(ch=='I'){
                scanf("%d %c",&k,&ch);k++;
                x=find(k);
                splay(x,0);
                y=++cnt;n++;
                e[y].ch[1]=e[x].ch[1];e[y].fa=x;e[y].key=ch-'a'+1;
                e[e[x].ch[1]].fa=y;e[x].ch[1]=y;
                updata(y);updata(x);
                continue;
            }
        }
        return 0;
    }
  • 相关阅读:
    Mongdb 简单增删改查
    mongdb的安装
    VO,DO,DTO,PO,POJO,EJB
    JavaScript是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式!
    判断DataTale中判断某个字段中包含某个数据
    查询表中某个字段的值出现次数大于1的数据
    判断对象数组中是否含有某个对象。
    C# datatable 重新排序
    jquery 验证大于0的整数
    jQuery 心跳请求
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5919693.html
Copyright © 2020-2023  润新知