zoukankan      html  css  js  c++  java
  • BZOJ2329 HNOI2011 括号修复 splay+贪心

    找平衡树练习题的时候发现了这道神题,可以说这道题是近几年单考splay的巅峰之作了。

    题目大意:给出括号序列,实现区间翻转,区间反转和区间更改。查询区间最少要用几次才能改成合法序列。

    分析:

      首先我们单看查询操作。不妨想象一下存在着一个栈,往里面入栈和出栈,那么从原序列中取出一对(),对应着一个入和一个出。那么当)的前面再也找不到(与之对应的时候,)就要被更改成(。

      这有什么用呢?我们会发现,删除一对()对答案不具有影响。接着我们删除所有可以匹配的括号,得到一个))))))((((((这样的序列。

      这个的答案是什么?由于对答案没有影响,我们单独考虑这个序列。我们把这个序列分成两部分考虑,对于由)构成的部分,取2的最大倍数个,其中的一半都要换成(,对于可能的多余的一个,我们一定将它变成(,接着用同样的想法考虑另一半,由于另一半一定是2的倍数个,所以答案加上另一半的一半。总的来说,答案等于ceil(“)序列长度”/2)+ceil("(序列长度"/2)

      修改操作怎么实现?假设我们有两棵括号序列正好相反的平衡树,那么区间反转操作可以视为将另一棵的这一部分嫁接过来,再把自己的这一部分嫁接过去。接着update答案即可。在草稿纸上面画一下区间翻转操作,发现翻转后的原序列与它的反序列在图形上对称。即翻转后序列的)序列等于反转后(序列长度。反之也是如此。那么这两个操作就很好解决了。

      接下来是区间更改操作,它可以覆盖掉另外两个操作,同时反转操作对它产生反转更改标记的影响。

    代码:

    splay容易打错,我用了treap替代它。

      1 #include<bits/stdc++.h>
      2 #pragma GCC optimize(2)
      3 #define L (t[now].ch[0])
      4 #define R (t[now].ch[1])
      5 using namespace std;
      6 
      7 struct node{
      8     int data,sz,lk[2],rk[2];
      9     int ch[2],key;
     10     int lzfz,lzrp,lzinv;
     11 }t[320000];
     12 int n,m,Num;
     13 int root1;
     14 char str[120000];
     15 
     16 void push_down1(int now){
     17     if(now == 0) return;
     18     swap(t[now].lk[0],t[now].rk[1]);
     19     swap(t[now].rk[0],t[now].lk[1]);
     20     swap(L,R);
     21     t[L].lzfz ^= 1; t[R].lzfz ^= 1;t[now].lzfz ^= 1;
     22 }
     23 
     24 void push_down2(int now){
     25     if(now == 0) return;
     26     swap(t[now].lk[0],t[now].lk[1]);
     27     swap(t[now].rk[0],t[now].rk[1]);
     28     t[L].data *= -1;t[R].data *= -1;
     29     t[L].lzinv ^= 1; t[R].lzinv ^= 1;t[now].lzinv ^= 1;
     30     t[L].lzrp *= -1; t[R].lzrp *= -1;
     31 }
     32 
     33 void push_down3(int now){
     34     if(now == 0) return;
     35     t[L].lzfz = t[L].lzinv = 0; t[R].lzfz = t[R].lzinv = 0;
     36     t[L].data = t[R].data = t[now].lzrp;
     37     t[L].lzrp = t[now].lzrp;t[R].lzrp = t[now].lzrp;
     38     //last buding paichu
     39     t[L].lk[0] = t[L].lk[1] = t[L].rk[0] = t[L].rk[1] = 0;
     40     t[R].lk[0] = t[R].lk[1] = t[R].rk[0] = t[R].rk[1] = 0;
     41     //last buding paichu
     42     if(t[now].lzrp == 1){
     43     t[L].rk[0] = t[L].lk[1] = t[L].sz;
     44     t[R].rk[0] = t[R].lk[1] = t[R].sz;
     45     }else{
     46     t[L].lk[0] = t[L].rk[1] = t[L].sz;
     47     t[R].lk[0] = t[R].rk[1] = t[R].sz;
     48     }
     49     t[now].lzrp = 0;
     50 }
     51 
     52 void push_up(int now){
     53     if(t[now].lzfz) push_down1(now);
     54     if(t[now].lzinv) push_down2(now);
     55     if(t[now].lzrp) push_down3(now);
     56     //rouyan chachu loudong
     57     if(t[L].lzfz) push_down1(L);if(t[R].lzfz) push_down1(R);
     58     if(t[L].lzinv) push_down2(L);if(t[R].lzinv) push_down2(R);
     59     if(t[L].lzrp) push_down3(L);if(t[R].lzrp) push_down3(R);
     60 
     61     t[now].sz = t[L].sz + t[R].sz + 1;
     62     t[now].lk[0] = t[L].lk[0];t[now].rk[0] = t[L].rk[0];
     63     t[now].lk[1] = t[L].lk[1];t[now].rk[1] = t[L].rk[1];
     64     if(t[now].data == 1)t[now].rk[0]++;
     65     else if(t[now].rk[0])t[now].rk[0]--;else t[now].lk[0]++;
     66     if(t[now].data == -1)t[now].rk[1]++;
     67     else if(t[now].rk[1])t[now].rk[1]--;else t[now].lk[1]++;
     68     if(t[now].rk[0] >= t[R].lk[0])t[now].rk[0] += t[R].rk[0]-t[R].lk[0];
     69     else t[now].lk[0] += t[R].lk[0]-t[now].rk[0],t[now].rk[0]=t[R].rk[0];
     70     if(t[now].rk[1] >= t[R].lk[1]) t[now].rk[1] += t[R].rk[1]-t[R].lk[1];
     71     else t[now].lk[1] += t[R].lk[1]-t[now].rk[1],t[now].rk[1]=t[R].rk[1];
     72 }
     73 
     74 int merge(int r1,int r2){
     75     if(t[r1].lzfz) push_down1(r1); if(t[r1].lzinv) push_down2(r1);
     76     if(t[r1].lzrp) push_down3(r1); if(t[r2].lzfz) push_down1(r2);
     77     if(t[r2].lzinv) push_down2(r2); if(t[r2].lzrp) push_down3(r2);
     78     if(r1 == 0) return r2; if(r2 == 0) return r1;
     79     if(t[r1].key < t[r2].key){
     80     t[r1].ch[1] = merge(t[r1].ch[1],r2);
     81     push_up(r1); return r1;
     82     }else{
     83     t[r2].ch[0] = merge(r1,t[r2].ch[0]);
     84     push_up(r2); return r2;
     85     }
     86 }
     87 
     88 pair <int,int> split(int now,int sz){
     89     if(t[now].lzfz) push_down1(now);
     90     if(t[now].lzinv) push_down2(now);
     91     if(t[now].lzrp) push_down3(now);
     92     if(sz == 0) return make_pair(0,now);
     93     if(sz >= t[now].sz) return make_pair(now,0);
     94     pair <int,int> pi;
     95     if(t[L].sz >= sz)
     96     pi=split(L,sz),t[now].ch[0]=pi.second,pi.second=now;
     97     else
     98     pi=split(R,sz-t[L].sz-1),t[now].ch[1]=pi.first,pi.first=now;
     99     push_up(pi.first); push_up(pi.second);
    100     return pi;
    101 }
    102 
    103 void flip(int l,int r){
    104     pair <int,int> pi = split(root1,r);
    105     pair <int,int> pp = split(pi.first,l-1);
    106     int now = pp.second;
    107     if(t[now].lzfz) push_down1(now);
    108     if(t[now].lzinv) push_down2(now);
    109     if(t[now].lzrp) push_down3(now);
    110     t[now].lzfz ^= 1;
    111     root1 = merge(merge(pp.first,pp.second),pi.second);
    112 }
    113 
    114 void link(int l,int r){
    115     pair <int,int> pi = split(root1,r);
    116     pair <int,int> pp = split(pi.first,l-1);
    117     int now = pp.second;
    118     if(t[now].lzfz) push_down1(now);
    119     if(t[now].lzinv) push_down2(now);
    120     if(t[now].lzrp) push_down3(now);
    121     t[now].lzinv ^= 1;t[now].data *= -1;
    122     root1 = merge(merge(pp.first,pp.second),pi.second);
    123 }
    124 
    125 void get_ans(int l,int r){
    126     pair <int,int> pi = split(root1,r);
    127     pair <int,int> pp = split(pi.first,l-1);
    128     int now = pp.second;
    129     if(t[now].lzfz) push_down1(now);
    130     if(t[now].lzrp) push_down2(now);
    131     if(t[now].lzinv) push_down3(now);
    132     int ans = ceil(t[now].lk[0]/2.0)+ceil(t[now].rk[0]/2.0);
    133     printf("%d
    ",ans);
    134     root1 = merge(merge(pp.first,pp.second),pi.second);
    135 }
    136 
    137 void insert(int &now,char what,int place){
    138     t[++Num].data=(what=='('?1:-1);t[Num].sz=1;t[Num].key=rand()%6547845;
    139     if(what == '(')t[Num].rk[0] = 1,t[Num].lk[1] = 1;
    140     else t[Num].lk[0] = 1,t[Num].rk[1] = 1;
    141     pair<int,int> p1 = split(now,place);
    142     now = merge(merge(p1.first,Num),p1.second);
    143 }
    144 
    145 void read(){
    146     scanf("%d%d",&n,&m);
    147     for(int i=1;i<=n;i++){
    148     char ch = getchar();
    149     while(ch != '(' && ch != ')') ch = getchar();
    150     str[i] = ch;
    151     }
    152     for(int i=1;i<=n;i++){
    153     if(str[i] == '('){insert(root1,'(',i);}
    154     else {insert(root1,')',i);}
    155     }
    156 }
    157 
    158 void work(){
    159     for(int i=1;i<=m;i++){
    160     int cg,l,r; scanf("%d%d%d",&cg,&l,&r);
    161     switch(cg){
    162     case 0:{get_ans(l,r);break;}
    163     case 2:{flip(l,r);break;}
    164     case 1:{link(l,r);break;}
    165     }
    166     }
    167 }
    168 
    169 int main(){
    170     srand(123456451);
    171     read();
    172     work();
    173     return 0;
    174 }
  • 相关阅读:
    Linux新手入门:通过chmod改变文件权限--转
    一个非常好的性格切割问题
    Weka算法Classifier-tree-J48源代码分析(一个)基本数据结构和算法
    百度地图3.1课程—检索演示
    JAVA在IO流量汇总
    crm2011i创建nt类型字段
    学习vi和vim编辑(3):一个简单的文本编辑器(2)
    禹洲:我们这一代人的困惑
    D其他项目打电话AL工程EF Model
    HDU 2289 Cup(可以二分法,但是除了它的一半?)
  • 原文地址:https://www.cnblogs.com/1-1-1-1/p/8203960.html
Copyright © 2011-2022 走看看