zoukankan      html  css  js  c++  java
  • Uva 11996 Jewel Magic (Splay)

    Jewel Magic

    Description

    I am a magician. I have a string of emeralds and pearls. I may insert new jewels in the string, or remove old ones. I may even reverse a consecutive part of the string. At anytime, if you point to two jewels and ask me, what is the length of the longest common prefix (LCP) of jewel strings starting from these two jewels, I can answer your question instantly. Can you do better than me? Formally, you’ll be given a string of 0 and 1. You’re to deal with four kinds of operations (in the following descriptions, L denotes the current length of the string, and jewel positions are number 1 to L numbered from left to right): 1 p c Insert a jewel c after position p (0 ≤ p ≤ L, p = 0 means insert before the whole string). c = 0 means emerald, c = 1 represents pearl. 2 p Remove the jewel at position p (1 ≤ p ≤ L). 3 p1 p2 Reverse the part starting from position p1, ending at position p2 (1 ≤ p1 < p2 ≤ L) 4 p1 p2 Output the LCP length of jewel strings starting from p1 and p2 (1 ≤ p1 < p2 ≤ L).

    Input

    There will be several test cases. The first line of each test case contains an integer n and m (1 ≤ n, m ≤ 200, 000), where n is the number of pearls initially, m is the number of operations. The next line contains a 01 string of length n. Each of the next m lines contains an operation. The input is terminated by end-of-file (EOF).

    Output

    For each type-4 operation, output the answer.

    Explanation:

    String after operation 1 0 1: 1000100001100

    String after operation 3 7 10: 1000101000100

    String after operation 2 9: 100010100100

    Sample Input

    12 9

    000100001100

    1 0 1

    4 2 6

    3 7 10

    4 1 7

    2 9

    4 3 11

    4 1 9

    4 1 7

    4 2 3

    Sample Output

    3

    6

    2

    0

    3

    2

    /*
     * UVa 11996 Jewel Magic
     *
     * 给你一个1~n的的01串,进行下面四个操作
     * 1 p c 在第p个字符后面插入c
     * 2 p   删除第p个字符
     * 3 x y 翻转区间[x,y]的字符
     * 4 x y 求从x和y开始的后缀的lcp
     *
     * 前三个都是Splay的基本操作,很容易实现,第四个操作用后缀数组显然不行,考虑用字符串hash
     * 每个节点新增加两个变量,这个子树的hash值和反转的hash值,然后二分长度回答即可
     */
    
    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    using namespace std;
    
    #define Key_value ch[ch[root][1]][0]
    const int MAXN = 400010;
    const int INF = 0X3F3F3F3F;
    const int MOD = 1000000000+7;
    int fa[MAXN],ch[MAXN][2],key[MAXN],sz[MAXN],rev[MAXN];
    long long ha[MAXN],fha[MAXN];
    long long Hash[MAXN];
    int root,tot1;
    int s[MAXN],tot2;
    char str[MAXN];
    int n,m;
    
    void NewNode(int &r,int pre,int k)
    {
        if(tot2) r=s[tot2--];
        else r=++tot1;
        ch[r][0]=ch[r][1]=0;
        fa[r]=pre;
        sz[r]=1;
        rev[r]=0;
        ha[r]=k;
        fha[r]=k;
        key[r]=k;
    }
    void Update_Rev(int r)
    {
        if(r==0) return;
        swap(ch[r][0],ch[r][1]);
        swap(ha[r],fha[r]);
        rev[r]^=1;
    }
    void Push_Up(int r)
    {
        int lson=ch[r][0],rson=ch[r][1];
        sz[r]=sz[lson]+sz[rson]+1;
        long long lha=ha[lson],rha=ha[rson];
         long long lfha=fha[lson],rfha=fha[rson];
         ha[r]=lha+(key[r]*Hash[sz[lson]])%MOD+(rha*Hash[sz[lson]+1])%MOD;
         ha[r]%=MOD;
         fha[r]=rfha+(key[r]*Hash[sz[rson]])%MOD+(lfha*Hash[sz[rson]+1])%MOD;
         fha[r]%=MOD;
    }
    void Push_Down(int r)
    {
        if(rev[r])
        {
            Update_Rev(ch[r][0]);
            Update_Rev(ch[r][1]);
            rev[r]=0;
        }
    }
    void Build(int &x,int l,int r,int pre)
    {
        if(l>r) return;
        int mid=(l+r)/2;
        NewNode(x,pre,str[mid]-'0');
        Build(ch[x][0],l,mid-1,x);
        Build(ch[x][1],mid+1,r,x);
        Push_Up(x);
    }
    void Init()
    {
        Hash[0]=1;
        for(int i=1;i<MAXN;i++) Hash[i]=(Hash[i-1]*2)%MOD;
        root=tot1=tot2=0;
        ch[root][0]=ch[root][1]=sz[root]=rev[root]=fa[root]=0;
        NewNode(root,0,-1);
        NewNode(ch[root][1],root,-1);
        Build(Key_value,0,n-1,ch[root][1]);
        Push_Up(ch[root][1]);
        Push_Up(root);
    }
    void Rotate(int x,int d)
    {
        int y=fa[x];
        Push_Down(y);
        Push_Down(x);
        ch[y][!d]=ch[x][d];
        fa[ch[x][d]]=y;
        if(fa[y]) ch[fa[y]][ch[fa[y]][1]==y]=x;
        fa[x]=fa[y];
        ch[x][d]=y;
        fa[y]=x;
        Push_Up(y);
    }
    void Splay(int r,int goal)
    {
        Push_Down(r);
        while(fa[r]!=goal)
        {
            if(fa[fa[r]]==goal)
            {
                Push_Down(fa[r]);
                Push_Down(r);
                Rotate(r,ch[fa[r]][0]==r);
            }
            else
            {
                Push_Down(fa[fa[r]]);
                Push_Down(fa[r]);
                Push_Down(r);
                int y=fa[r];
                int d=(ch[fa[y]][0]==y);
                if(ch[y][d]==r)
                {
                    Rotate(r,!d);
                    Rotate(r,d);
                }
                else
                {
                    Rotate(y,d);
                    Rotate(r,d);
                }
            }
        }
        Push_Up(r);
        if(goal==0) root=r;
    }
    int Get_Kth(int r,int k)
    {
        Push_Down(r);
        int t=sz[ch[r][0]]+1;
        if(t==k) return r;
        if(t>k) return Get_Kth(ch[r][0],k);
        else return Get_Kth(ch[r][1],k-t);
    }
    void Erase(int r)
    {
        if(r)
        {
            s[++tot2]=r;
            Erase(ch[r][0]);
            Erase(ch[r][1]);
        }
    }
    void update_int(int x,int y)
    {
        Splay(Get_Kth(root,x+1),0);
        Splay(Get_Kth(root,x+2),root);
        NewNode(Key_value,ch[root][1],y);
        Push_Up(ch[root][1]);
        Push_Up(root);
    }
    void update_del(int x)
    {
        Splay(Get_Kth(root,x),0);
        Splay(Get_Kth(root,x+2),root);
        Erase(Key_value);
        fa[Key_value]=0;
        Key_value=0;
        Push_Up(ch[root][1]);
        Push_Up(root);
    }
    void update_rev(int x,int y)
    {
        Splay(Get_Kth(root,x),0);
        Splay(Get_Kth(root,y+2),root);
        Update_Rev(Key_value);
        Push_Up(ch[root][1]);
        Push_Up(root);
    }
    bool check(int len,int l,int r)
    {
        Splay(Get_Kth(root,l),0);
        Splay(Get_Kth(root,l+len+1),root);
        long long k1=ha[Key_value];
        Splay(Get_Kth(root,r),0);
        Splay(Get_Kth(root,r+len+1),root);
        long long k2=ha[Key_value];
        return k1==k2;
    }
    int query_lcp(int x,int y)
    {
        int l=0,r=sz[root]-1-y;
        int res;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid,x,y)) l=mid+1,res=mid;
            else r=mid-1;
        }
        return res;
    }
    
    int main()
    {
        int t,x,y,z;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            scanf("%s",str);
            Init();
            while(m--)
            {
                scanf("%d",&t);
                if(t==1)
                {
                    scanf("%d%d",&x,&y);
                    update_int(x,y);
                }
                else if(t==2)
                {
                    scanf("%d",&x);
                    update_del(x);
                }
                else if(t==3)
                {
                    scanf("%d%d",&x,&y);
                    update_rev(x,y);
                }
                else
                {
                    scanf("%d%d",&x,&y);
                    printf("%d
    ",query_lcp(x,y));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    ios开发--KVO浅析
    为iPhone6设计自适应布局
    详解iOS多线程 (转载)
    一些Iphone sqlite 的包装类
    ios多线程和进程的区别(转载)
    数据链路层解析
    物理层解析,交换机命令行
    计算机网络,数制模型
    java爬虫中jsoup的使用
    hadoop+zookeeper集群高可用搭建
  • 原文地址:https://www.cnblogs.com/wangdongkai/p/5767011.html
Copyright © 2011-2022 走看看