您的位置:首页 > 其它

BZOJ2329 HNOI2011 括号修复 splay+贪心

2018-01-05 13:32 507 查看

找平衡树练习题的时候发现了这道神题,可以说这道题是近几年单考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\n",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 }

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: