zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    多重背包POJ1276不要求恰好装满 poj1014多重背包恰好装满
    哈理工1053完全背包
    求最小公倍数与最大公约数的函数
    Bus Pass ZOJ 2913 BFS 最大中取最小的
    POJ 3624 charm bracelet 01背包 不要求装满
    HavelHakimi定理(判断一个序列是否可图)
    z0j1008Gnome Tetravex
    ZOJ 1136 Multiple BFS 取模 POJ 1465
    01背包 擎天柱 恰好装满 zjut(浙江工业大学OJ) 1355
    zoj 2412 水田灌溉,求连通分支个数
  • 原文地址:https://www.cnblogs.com/chadinblog/p/5919693.html
Copyright © 2011-2022 走看看