zoukankan      html  css  js  c++  java
  • BZOJ 2329/2209 [HNOI2011]括号修复 (splay)

    题目大意:

    让你维护一个括号序列,支持

    1.区间修改为同一种括号

    2.区间内所有括号都反转

    3.翻转整个区间,括号的方向不变

    4.查询把某段区间变为合法的括号序列,至少需要修改多少次括号

    给跪了,足足$de$了$3h$

    感觉这道题的思维难度比维修数列高多了

    前三个操作都非常好搞,都是区间打标记

    注意下推标记的顺序,子树根如果有区间覆盖标记,那么子树内所有节点的反转和翻转标记都失效了,要清空

    而下传到同一节点的区间覆盖和反转翻转标记不冲突

    我们下推标记时必须保证,下推后,两个子节点的状态拿来就能用,不用再进行额外的修改

    第四个操作,可以像维修数列那道题一样维护一个小$dp$,只不过这个$dp$更为复杂

    定义$f[x][0/1][0/1]$表示节点$x$表示的子树,左/右边剩余的左/右括号数量

    左边和右边表示的不是左右子树!

    状态 左边右括号01 和 右边左括号10 表示x子树的括号序列,正匹配‘()’时,左边剩余的右括号和右边剩余的左括号一定不能被匹配,记录它们的数量

    状态 左边左括号00 和 右边右括号11 表示x子树的括号序列,反匹配‘)(’时,左边剩余的左括号和右边剩余的右括号一定不能被匹配,记录它们的数量

    转移就很显然了

    void pushup(int x)
    {
        int ls=ch[x][0],rs=ch[x][1],w=val[x]?1:-1;
        f[x][0][0]=f[ls][0][0]+max(0,f[rs][0][0]-w-f[ls][1][1]);
        f[x][0][1]=f[ls][0][1]+max(0,f[rs][0][1]+w-f[ls][1][0]);
        f[x][1][0]=f[rs][1][0]+max(0,f[ls][1][0]-w-f[rs][0][1]);
        f[x][1][1]=f[rs][1][1]+max(0,f[ls][1][1]+w-f[rs][0][0]);
        sz[x]=sz[ls]+sz[rs]+1;
    }

    而 覆盖/翻转/反转 操作同样需要修改dp,打表找规律可得

    void Rpl(int x,int w) //覆盖
    {
        memset(f[x],0,sizeof(f[x]));
        f[x][w^1][w]=f[x][w][w]=sz[x]; //不论反匹配还是正匹配,肯定全都不能被匹配上
        val[x]=w, tag[x]=1, rev[x]=0, inv[x]=0; //去除反转翻转标记,否则可能会下传相反的覆盖标记
    }
    void Rev(int x) //翻转,把序列翻转
    {
        swap(f[x][0][0],f[x][1][0]); //反匹配变为正匹配,括号的位置改变,左右数量交换
        swap(f[x][0][1],f[x][1][1]);
        swap(ch[x][0],ch[x][1]); rev[x]^=1;
    }
    void Inv(int x) //反转,左括号变右括号
    {
        swap(f[x][0][0],f[x][0][1]); //反匹配变为正匹配,括号的位置不变,左右数量不变
        swap(f[x][1][0],f[x][1][1]);
        val[x]^=1; inv[x]^=1;
    }

    剩下就是常规的$splay$了

    此外,一定要在$find$函数里下推标记,否则会找到错误的位置!

    千万千万不要打错变量名,我有足足1h30min浪费在了打错的变量名上了..

      1 #include <queue>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #define N1 101000
      7 #define M1 2010
      8 #define S1 (N1<<1)
      9 #define T1 (N1<<2)
     10 #define ll long long
     11 #define uint unsigned int
     12 #define rint register int 
     13 #define dd double
     14 #define il inline 
     15 #define inf 233333333
     16 using namespace std;
     17 
     18 int gint()
     19 {
     20     int ret=0,fh=1;char c=getchar();
     21     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
     22     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
     23     return ret*fh;
     24 }
     25 int n,m;
     26 int a[N1];
     27 char str[N1];
     28 struct Splay{
     29 #define root ch[0][1]
     30 int ch[N1][2],fa[N1],tag[N1],val[N1],rev[N1],inv[N1],sz[N1],f[N1][2][2];
     31 int idf(int x){return ch[fa[x]][0]==x?0:1;}
     32 void Rpl(int x,int w)
     33 {
     34     memset(f[x],0,sizeof(f[x]));
     35     f[x][w^1][w]=f[x][w][w]=sz[x];
     36     val[x]=w, tag[x]=1, rev[x]=0, inv[x]=0;
     37 }
     38 void Rev(int x)
     39 {
     40     swap(f[x][0][0],f[x][1][0]);
     41     swap(f[x][0][1],f[x][1][1]);
     42     swap(ch[x][0],ch[x][1]); rev[x]^=1;
     43 }
     44 void Inv(int x) //左括号变有括号。
     45 {
     46     swap(f[x][0][0],f[x][0][1]);
     47     swap(f[x][1][0],f[x][1][1]);
     48     val[x]^=1; inv[x]^=1;
     49 }
     50 void pushdown(int x)
     51 {
     52     int ls=ch[x][0],rs=ch[x][1];
     53     if(tag[x])
     54     {
     55         if(ls) Rpl(ls,val[x]);
     56         if(rs) Rpl(rs,val[x]);
     57         inv[x]=rev[x]=tag[x]=0; return;
     58     }
     59     if(rev[x])
     60     {
     61         if(ls) Rev(ls);
     62         if(rs) Rev(rs);
     63         rev[x]^=1;
     64     }
     65     if(inv[x])
     66     {
     67         if(ls) Inv(ls);
     68         if(rs) Inv(rs);
     69         inv[x]^=1;
     70     }
     71 }
     72 void pushup(int x)
     73 {
     74     int ls=ch[x][0],rs=ch[x][1],w=val[x]?1:-1;
     75     f[x][0][0]=f[ls][0][0]+max(0,f[rs][0][0]-w-f[ls][1][1]);
     76     f[x][0][1]=f[ls][0][1]+max(0,f[rs][0][1]+w-f[ls][1][0]);
     77     f[x][1][0]=f[rs][1][0]+max(0,f[ls][1][0]-w-f[rs][0][1]);
     78     f[x][1][1]=f[rs][1][1]+max(0,f[ls][1][1]+w-f[rs][0][0]);
     79     sz[x]=sz[ls]+sz[rs]+1;
     80 }
     81 void rot(int x)
     82 {
     83     int y=fa[x],ff=fa[y],px=idf(x),py=idf(y);
     84     fa[ch[x][px^1]]=y,ch[y][px]=ch[x][px^1];
     85     ch[x][px^1]=y,fa[y]=x,ch[ff][py]=x,fa[x]=ff;
     86     pushup(y),pushup(x);
     87 }
     88 //int stk[N1],tp;
     89 void splay(int x,int to)
     90 {
     91     int y=x; to=fa[to]; 
     92     while(fa[x]!=to)
     93     {
     94         y=fa[x];
     95         if(fa[y]==to) rot(x);
     96         else if(idf(y)==idf(x)) rot(y),rot(x);
     97         else rot(x),rot(x);
     98     }
     99     /*stk[++tp]=x;
    100     while(fa[y]){stk[++tp]=fa[y],y=fa[y];}
    101     while(tp){pushdown(stk[tp--]);}*/
    102 }
    103 int build(int l,int r,int ff)
    104 {
    105     if(l>r) return 0;
    106     int mid=(l+r)>>1,x=mid+1;
    107     val[x]=a[mid];fa[x]=ff;
    108     ch[x][0]=build(l,mid-1,x);
    109     ch[x][1]=build(mid+1,r,x);
    110     pushup(x);
    111     return x;
    112 }
    113 int find(int K)
    114 {
    115     int x=root;
    116     while(1)
    117     {
    118         pushdown(x);
    119         if(K>sz[ch[x][0]]){
    120             K-=sz[ch[x][0]];
    121             if(K==1) {pushdown(x);return x;}
    122             K--; x=ch[x][1];
    123         }else{
    124             x=ch[x][0];
    125         }
    126     }
    127 }
    128 int split(int l,int r)
    129 {
    130     int x=find(l); splay(x,root);
    131     int y=find(r+2); splay(y,ch[x][1]);
    132     return ch[y][0];
    133 }
    134 void Replace(int l,int r,int w)
    135 {
    136     int x=split(l,r);
    137     val[x]=w; tag[x]=1; rev[x]=inv[x]=0;
    138     memset(f[x],0,sizeof(f[x]));
    139     f[x][w^1][w]=f[x][w][w]=sz[x];
    140 }
    141 void Swp(int l,int r)
    142 {
    143     int x=split(l,r);
    144     Rev(x);
    145 }
    146 void Invert(int l,int r)
    147 {
    148     int x=split(l,r), ls=ch[x][0], rs=ch[x][1];
    149     swap(f[x][0][0],f[x][0][1]), swap(f[x][1][0],f[x][1][1]);
    150     val[x]^=1; inv[x]^=1; //val[ls]^=1; val[rs]^=1; 
    151 }
    152 int Query(int l,int r)
    153 {
    154     int x=split(l,r);
    155     return f[x][0][1]/2+((f[x][0][1]&1)?1:0)+f[x][1][0]/2+((f[x][1][0]&1)?1:0);
    156 }
    157 void debug()
    158 {
    159     for(int i=2;i<=n+1;i++)
    160         printf("%c",val[i]?')':'(');
    161     puts("");
    162 }
    163 #undef root
    164 }s;
    165 
    166 int main()
    167 {
    168     //freopen("t2.in","r",stdin);
    169     scanf("%d%d",&n,&m);
    170     int i,j,x,y,w;
    171     scanf("%s",str+1);
    172     for(i=1;i<=n;i++) a[i]=(str[i]=='(')?0:1;
    173     a[0]=0,a[n+1]=1;
    174     s.ch[0][1]=s.build(0,n+1,0);
    175     for(i=1;i<=m;i++)
    176     {
    177         scanf("%s",str);
    178         if(str[0]=='R'){
    179             x=gint(), y=gint(), scanf("%s",str); 
    180             w=(str[0]=='(')?0:1;
    181             s.Replace(x,y,w);
    182         }else if(str[0]=='S'){
    183             x=gint(), y=gint();
    184             s.Swp(x,y);
    185         }else if(str[0]=='I'){
    186             x=gint(), y=gint();
    187             s.Invert(x,y);
    188         }else if(str[0]=='Q'){
    189             x=gint(), y=gint();
    190             printf("%d
    ",s.Query(x,y));
    191         }
    192         //s.debug();
    193     }
    194     return 0;
    195 }

    附赠对拍程序以及数据生成器,建议自己写,考场上这种题不拍简直找死

    暴力:

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N1 1010
    #define M1 2010
    #define S1 (N1<<1)
    #define T1 (N1<<2)
    #define ll long long
    #define uint unsigned int
    #define rint register int 
    #define dd double
    #define il inline 
    #define inf 233333333
    using namespace std;
    
    int gint()
    {
        int ret=0,fh=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
        while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
        return ret*fh;
    }
    int n,m;
    int a[N1],tmp[N1];
    char str[N1];
    
    void debug()
    {
        for(int i=1;i<=n;i++)
            printf("%c",a[i]?')':'(');
        puts("");
    }
    
    int main()
    {
        freopen("t2.in","r",stdin);
        scanf("%d%d",&n,&m);
        int i,j,x,y,w;
        scanf("%s",str+1);
        for(i=1;i<=n;i++) a[i]=(str[i]=='(')?0:1;
        for(i=1;i<=m;i++)
        {
            scanf("%s",str);
            if(str[0]=='R'){
                x=gint(), y=gint(), scanf("%s",str); 
                w=(str[0]=='(')?0:1;
                for(j=x;j<=y;j++) a[j]=w;
            }else if(str[0]=='S'){
                x=gint(), y=gint();
                for(j=x;j<=y;j++) tmp[j-x+1]=a[j];
                for(j=x;j<=y;j++) a[j]=tmp[y-j+1];//y-j+1
            }else if(str[0]=='I'){
                x=gint(), y=gint();
                for(j=x;j<=y;j++) a[j]^=1;
            }else if(str[0]=='Q'){
                x=gint(), y=gint();
                int sum=0,ans=0,ret=0;
                for(j=x;j<=y;j++)
                {
                    if(!a[j]) sum++;
                    else if(sum>0) sum--;
                    else ans++;
                }
                ret+=ans/2+((ans&1)?1:0); sum=ans=0;
                for(j=y;j>=x;j--)
                {
                    if(a[j]) sum++;
                    else if(sum>0) sum--;
                    else ans++;
                }
                ret+=ans/2+((ans&1)?1:0);
                printf("%d
    ",ret);
            }
            //debug();
        }
        return 0;
    }
    View Code

    数据生成器:

    #include <bits/stdc++.h>
    using namespace std;
    
    
    int main()
    {
        srand(time(NULL));
        int n=20,m=20,i,x,l,r,t;
        printf("%d %d
    ",n,m);
        for(i=1;i<=n;i++) x=rand()%2,printf("%c",(x&1)?')':'(');
        puts("");
        for(i=1;i<=m;i++)
        {
            x=rand()%4; l=rand()%n+1; r=rand()%n+1; 
            if(l>r) swap(l,r);
            if(x==0){
                x=rand()%2;
                printf("Replace %d %d %c
    ",l,r,(x&1)?')':'(');
            }else if(x==1){
                printf("Swap %d %d
    ",l,r);
            }else if(x==2){
                printf("Invert %d %d
    ",l,r);
            }else{
                l=(rand()%(n/2))*2+1,r=(rand()%(n/2)+1)*2;
                if(l>r) swap(l,r);
                printf("Query %d %d
    ",l,r);
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    笨办法学Python——学习笔记4
    意识、语言、文字和程序感想
    笨办法学Python——学习笔记3
    把vim作为shell ide
    HDUYuna's confusion 树状数组 Or Multiset
    POJ3252 Round Numbers 组合数学
    HDU3874 Necklace 树状数组+离线处理
    UVA10212 The Last Nonzero Digit. 分解质因子+容斥定理
    HDU1041 Computer Transformation 大数
    HDUFish买电脑 二分查找
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10158900.html
Copyright © 2011-2022 走看看