• bzoj 2209: [Jsoi2011]括号序列 splay


    2209: [Jsoi2011]括号序列

    Time Limit: 20 Sec  Memory Limit: 259 MB
    Submit: 833  Solved: 392
    [Submit][Status]

    Description

    Input

    输入数据的第一行包含两个整数N和Q,分别表示括号序列的长度,以及操作的个数。 第二行包含一个长度为N的括号序列。 接下来Q行,每行三个整数t、x和y,分别表示操作的类型、操作的开始位置和操作的结 束位置,输入数据保证x不小于y。其中t=0表示询问操作、t=1表示反转操作、t=2表示翻转操 作。

    Output

    对于每一个询问操作,输出一行,表示将括号序列的该子序列修改为配对,所需的最少改动 个数。

    Sample Input

    6 3
    )(())(
    0 1 6
    0 1 4
    0 3 4

    Sample Output

    2
    2
    0

    HINT

    100%的数据满足N,Q不超过10^5

      终于算是会写splay了,这道题涉及到splay的区间翻转,取反,询问以及lazy标记下放等操作,算是涵盖了splay的基本用法。

      合法的括号序列的一个性质是,以正括号为1,反括号为-1,合法序列和为0,且所有前缀权值和非负。顾可以通过类似于线段树求区间最大子段和方式维护,由于涉及到区间翻转,故改为splay维护。

      这次编写问题还是在标记同步上,具体来说,在get_kth()调用前一定要down(),修改子树后要讲修改后的值传回根节点。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define MAXN 210000
    #define MAXT 210000
    inline int min(int x,int y,int z)
    {
            return min(x,min(y,z));
    }
    inline int min(int a,int b,int c,int d)
    {
            return min(min(a,b),min(c,d));
    }
    inline int max(int x,int y,int z)
    {
            return max(x,max(y,z));
    }
    inline int max(int a,int b,int c,int d)
    {
            return max(max(a,b),max(c,d));
    }
    int num[MAXN];
    struct splay_tree
    {
            int ch[MAXT][2],pnt[MAXT];
            int val[MAXT],siz[MAXT],sum[MAXT],lx[MAXT][2],rx[MAXT][2];
            bool rev[MAXT],neg[MAXT];
            int stack[MAXT],tops;
            int topt;
            int root;
            splay_tree()
            {
                    topt=0,root=0;
                    tops=-1;
            }
            void reverse(int now)
            {
                    if (!now)return;
                    swap(lx[now][0],rx[now][0]);
                    swap(lx[now][1],rx[now][1]);
                    swap(ch[now][0],ch[now][1]);
                    rev[now]^=1;
            }
            void negate(int now)
            {
                    if (!now)return ;
                    val[now]=-val[now];
                    sum[now]=-sum[now];
                    swap(lx[now][0],lx[now][1]);
                    swap(rx[now][0],rx[now][1]);
                    lx[now][0]=-lx[now][0];
                    rx[now][0]=-rx[now][0];
                    lx[now][1]=-lx[now][1];
                    rx[now][1]=-rx[now][1];
                    neg[now]^=1;
            }
            void update(int now)
            {
                    lx[now][0]=min(lx[ch[now][0]][0],sum[ch[now][0]],sum[ch[now][0]]+val[now],sum[ch[now][0]]+val[now]+lx[ch[now][1]][0]);
                    lx[now][1]=max(lx[ch[now][0]][1],sum[ch[now][0]],sum[ch[now][0]]+val[now],sum[ch[now][0]]+val[now]+lx[ch[now][1]][1]);
                    rx[now][0]=min(rx[ch[now][1]][0],sum[ch[now][1]],sum[ch[now][1]]+val[now],sum[ch[now][1]]+val[now]+rx[ch[now][0]][0]);
                    rx[now][1]=max(rx[ch[now][1]][1],sum[ch[now][1]],sum[ch[now][1]]+val[now],sum[ch[now][1]]+val[now]+rx[ch[now][0]][1]);
                    sum[now]=sum[ch[now][0]]+sum[ch[now][1]]+val[now];
                    siz[now]=siz[ch[now][0]]+siz[ch[now][1]]+1;
            }
            void down(int now)
            {
                    if (rev[now])
                    {
                            reverse(ch[now][0]);
                            reverse(ch[now][1]);
                            rev[now]=0;
                    }
                    if (neg[now])
                    {
                            negate(ch[now][0]);
                            negate(ch[now][1]);
                            neg[now]=0;
                    }
            }
            void rotate(int now)
            {
                    int p=pnt[now],anc=pnt[p];
                    int dir=ch[p][0]==now;
                    if (anc)
                            ch[anc][ch[anc][1]==p]=now;
                    pnt[now]=anc;
                    pnt[ch[now][dir]]=p;
                    ch[p][1-dir]=ch[now][dir];
                    pnt[p]=now;
                    ch[now][dir]=p;
                    update(p);
                    update(now);
            }
            void splay(int now,int tp=0)
            {
                    int x=now;
                    tops=-1;
                    while (x!=tp)
                    {
                            stack[++tops]=x;
                            x=pnt[x];
                    }
                    while (~tops)
                    {
                            down(stack[tops--]);
                    }
                    while (now!=tp && pnt[now]!=tp)
                    {
                            int p=pnt[now],anc=pnt[p];
                            if (anc==tp)
                                    rotate(now);
                            else if ((ch[p][0]==now) == (ch[anc][0]==p))
                                    rotate(p),rotate(now);
                            else
                                    rotate(now),rotate(now);
                    }
                    if (tp==0)
                            root=now;
            }
            int get_kth(int now,int rk)
            {
                    if (!now)throw 1;
                    down(now);
                    if (siz[ch[now][0]]+1==rk)
                            return now;
                    if (siz[ch[now][0]]+1<rk)
                            return get_kth(ch[now][1],rk-siz[ch[now][0]]-1);
                    else
                            return get_kth(ch[now][0],rk);
            }
            void insert(int pos,int v)
            {
                    if (!root)
                    {
                            root=++topt;
                            pnt[topt]=0;
                            val[topt]=v;
                            update(topt);
                    }else if (!pos)
                    {
                            splay(get_kth(root,pos));
                            ch[root][0]=topt;
                            pnt[topt]=root;
                            val[topt]=v;
                            update(topt);
                            update(root);
                    }else
                    {
                            splay(get_kth(root,pos));
                            val[++topt]=v;
                            pnt[topt]=root;
                            ch[topt][1]=ch[root][1];
                            pnt[ch[root][1]]=topt;
                            ch[root][1]=topt;
                            update(topt);
                            update(root);
                    }
            }
            int get_result(int now)
            {
                    int res=0,t;
                    t=-lx[now][0];
                    res=t/2+t%2;
                    t=res*2+sum[now];
                    res+=abs(t)/2;
                    return res;
            }
            int query(int l,int r)
            {
                    if (l==1 && r==siz[root])
                            return get_result(root);
                    if (l==1)
                    {
                            splay(get_kth(root,r+1));
                            return get_result(ch[root][0]);
                    }
                    if (r==siz[root])
                    {
                            splay(get_kth(root,l-1));
                            return get_result(ch[root][1]);
                    }
                    splay(get_kth(root,r+1));
                    splay(get_kth(root,l-1),root);
                    return get_result(ch[ch[root][0]][1]);
            }
            void make_reverse(int l,int r)
            {
                    if (l==1 && r==siz[root])
                            return reverse(root);
                    if (l==1)
                    {
                            splay(get_kth(root,r+1));
                            reverse(ch[root][0]);
                            update(root);
                            return ;
                    }
                    if (r==siz[root])
                    {
                            splay(get_kth(root,l-1));
                            reverse(ch[root][1]);
                            update(root);
                            return ;
                    }
                    splay(get_kth(root,r+1));
                    splay(get_kth(root,l-1),root);
                    reverse(ch[ch[root][0]][1]);
                    update(ch[root][0]);
                    update(root);
            }
            void make_negate(int l,int r)
            {
                    if (l==1 && r==siz[root])
                            return negate(root);
                    if (l==1)
                    {
                            splay(get_kth(root,r+1));
                            negate(ch[root][0]);
                            update(root);
                            return ;
                    }
                    if (r==siz[root])
                    {
                            splay(get_kth(root,l-1));
                            negate(ch[root][1]);
                            update(root);
                            return ;
                    }
                    splay(get_kth(root,r+1));
                    splay(get_kth(root,l-1),root);
                    negate(ch[ch[root][0]][1]);
                    update(ch[root][0]);
                    update(root);
    
            }
            void scan(int now)
            {
                    if (!now)return ;
                    if (pnt[ch[now][0]]!=now && ch[now][0])throw 1;
                    if (pnt[ch[now][1]]!=now && ch[now][1])throw 2;
                    if (siz[now]!=siz[ch[now][0]]+siz[ch[now][1]]+1)throw 3;
                    scan(ch[now][0]);
                    printf("%d ",val[now]);
                    scan(ch[now][1]);
            }
    }pp;
    int main()
    {
            //freopen("input.txt","r",stdin);
            //    freopen("output.txt","w",stdout);
            int n,m,i,j,k,x,y,z;
            scanf("%d%d
    ",&n,&m);
            char ch;
            for (i=1;i<=n;i++)
            {
                    scanf("%c",&ch);
                    if (ch==')')
                            pp.insert(i-1,-1);
                    else
                            pp.insert(i-1,1);
            }
            int opt;
            for (i=1;i<=m;i++)
            {
                    scanf("%d%d%d",&opt,&x,&y);
                //    pp.scan(pp.root);printf("
    ");
                    if (opt==0)
                    {
                            printf("%d
    ",pp.query(x,y));
                    }else if (opt==1)
                    {
                            pp.make_negate(x,y);
                    }else if (opt==2)
                    {
                            pp.make_reverse(x,y);
                    }
            }
    }
    by mhy12345(http://www.cnblogs.com/mhy12345/) 未经允许请勿转载

    本博客已停用,新博客地址:http://mhy12345.xyz

  • 相关阅读:
    rsyslog imfile 模块说明
    正确的健身是啥意思——北漂18年(79)
    CC++ 内存对齐
    异步请求和超时控制
    dubbo入门(1)
    Query Cache Configuration
    perl 批量生成分区表
    perl 通过生成mysql 批量sql
    next 跳过当前循环
    last 退出当前循环
  • 原文地址:https://www.cnblogs.com/mhy12345/p/4106690.html
Copyright © 2020-2023  润新知