【HDOJ】3397 Sequence operation

线段树的应用,很不错的一道题目。结点属性包括:
(1)n1:1的个数;
(2)c1:连续1的最大个数;
(3)c0:连续0的最大个数;
(4)lc1/lc0:从区间左边开始,连续1/0的最大个数;
(5)rc1/rc0:从区间右边开始,连续1/0的最大个数;
(6)set:置区间为0/1的标记;
(7)flip:0->1, 1->0的标记。
采用延迟更新。每当更新set时,flip就置为false;每当更新flip时,其实就是c1/c0, lc1/lc0, rc1/rc0的交换。
对于询问最长连续1,共包括3种情况:左子树的最长连续1,右子树的最长连续1,以及左子树rc1+右子树lc1(注意有效范围区间)。

  1 /* 3397 */
  2 #include <iostream>
  3 #include <string>
  4 #include <map>
  5 #include <queue>
  6 #include <set>
  7 #include <vector>
  8 #include <algorithm>
  9 #include <cstdio>
 10 #include <cmath>
 11 #include <cstring>
 12 #include <climits>
 13 #include <cctype>
 14 using namespace std;
 15 
 16 #define MAXN 100005
 17 #define lson l, mid, rt<<1
 18 #define rson mid+1, r, rt<<1|1
 19 
 20 typedef struct {
 21     int set;
 22     int n1;
 23     int c1, c0;
 24     int lc1, lc0, rc1, rc0;
 25     bool flip;
 26 } node_t;
 27 
 28 node_t nd[MAXN<<2];
 29 int t, n, m, x;
 30 int op;
 31 
 32 void maintance_set(int op, int len, int rt) {
 33     nd[rt].set = op;
 34     nd[rt].flip = false;
 35     if (op) {
 36         nd[rt].n1 = nd[rt].c1 = nd[rt].lc1 = nd[rt].rc1 = len;
 37         nd[rt].c0 = nd[rt].lc0 = nd[rt].rc0 = 0;
 38     } else {
 39         nd[rt].n1 = nd[rt].c1 = nd[rt].lc1 = nd[rt].rc1 = 0;
 40         nd[rt].c0 = nd[rt].lc0 = nd[rt].rc0 = len;
 41     }
 42 }
 43 
 44 void maintance_flip(int len, int rt) {
 45     if (nd[rt].set >= 0)
 46         nd[rt].set = !nd[rt].set;
 47     else
 48         nd[rt].flip = !nd[rt].flip;
 49     nd[rt].n1 = len-nd[rt].n1;
 50     swap(nd[rt].c0, nd[rt].c1);
 51     swap(nd[rt].lc0, nd[rt].lc1);
 52     swap(nd[rt].rc0, nd[rt].rc1);
 53 }
 54 
 55 void PushUp(int l, int r, int rt) {
 56     int lb = rt<<1;
 57     int rb = rt<<1|1;
 58     int mid = (l+r)>>1;
 59     
 60     // update the number of 1
 61     nd[rt].n1 = nd[lb].n1 + nd[rb].n1;
 62     // update the longest continuous 1 and 0 in string
 63     nd[rt].c1 = max(
 64         max(nd[lb].c1, nd[rb].c1),
 65         nd[lb].rc1 + nd[rb].lc1
 66     );
 67     nd[rt].c0 = max(
 68         max(nd[lb].c0, nd[rb].c0),
 69         nd[lb].rc0 + nd[rb].lc0
 70     );
 71     // update the longest continuous 1/0 from left
 72     nd[rt].lc1 = nd[lb].lc1;
 73     nd[rt].lc0 = nd[lb].lc0;
 74     if (nd[lb].lc1 == mid-l+1)
 75         nd[rt].lc1 += nd[rb].lc1;
 76     if (nd[lb].lc0 == mid-l+1)
 77         nd[rt].lc0 += nd[rb].lc0;
 78     // update the longest continuous 1/0 from right
 79     nd[rt].rc1 = nd[rb].rc1;
 80     nd[rt].rc0 = nd[rb].rc0;
 81     if (nd[rb].rc1 == r-mid)
 82         nd[rt].rc1 += nd[lb].rc1;
 83     if (nd[rb].rc0 == r-mid)
 84         nd[rt].rc0 += nd[lb].rc0;
 85 }
 86 
 87 void PushDown(int l, int r, int rt) {
 88     int lb = rt<<1;
 89     int rb = rt<<1|1;
 90     int mid = (l+r)>>1;
 91     
 92     if (nd[rt].set >= 0) {
 93         // maintance_set lson & rson
 94         maintance_set(nd[rt].set, mid-l+1, lb);
 95         maintance_set(nd[rt].set, r-mid, rb);
 96         nd[rt].set = -1;
 97     }
 98     if (nd[rt].flip) {
 99         // maintance_flip lson & rson
100         maintance_flip(mid-l+1, lb);
101         maintance_flip(r-mid, rb);
102         nd[rt].flip = false;
103     }
104 }
105 
106 void build(int l, int r, int rt) {
107     nd[rt].set = -1;
108     nd[rt].flip = false;
109     if (l == r) {
110         scanf("%d", &x);
111         nd[rt].n1 = nd[rt].c1 = nd[rt].lc1 = nd[rt].rc1 = x;
112         nd[rt].c0 = nd[rt].lc0 = nd[rt].rc0 = !x;
113         return ;
114     }
115     int mid = (l+r)>>1;
116     build(lson);
117     build(rson);
118     PushUp(l, r, rt);
119 }
120 
121 // update to set [L, R] to op
122 void update1(int L, int R, int l, int r, int rt) {
123     if (L<=l && R>=r) {
124         maintance_set(op, r-l+1, rt);
125         return ;
126     }
127     int mid = (l+r)>>1;
128     PushDown(l, r, rt);
129     if (L <= mid)
130         update1(L, R, lson);
131     if (R > mid)
132         update1(L, R, rson);
133     PushUp(l, r, rt);
134 }
135 
136 // update to flip [L, R] one
137 void update2(int L, int R, int l, int r, int rt) {
138     if (L<=l && R>=r) {
139         maintance_flip(r-l+1, rt);
140         return ;
141     }
142     int mid = (l+r)>>1;
143     PushDown(l, r, rt);
144     if (L <= mid)
145         update2(L, R, lson);
146     if (R > mid)
147         update2(L, R, rson);
148     PushUp(l, r, rt);
149 }
150 
151 // query the sum of 1 in [L, R]
152 int query3(int L, int R, int l, int r, int rt) {
153     if (L<=l && R>=r)
154         return nd[rt].n1;
155     int mid = (l+r)>>1;
156     PushDown(l, r, rt);
157     int ret = 0;
158     if (L <= mid)
159         ret += query3(L, R, lson);
160     if (R > mid)
161         ret += query3(L, R, rson);
162     return ret;
163 }
164 
165 // query the longest continous 1 in [L, R]
166 int query4(int L, int R, int l, int r, int rt) {
167     if (L<=l && R>=r)
168         return nd[rt].c1;
169     int mid = (l+r)>>1;
170     PushDown(l, r, rt);
171     int ret;
172     if (L > mid) {
173         return query4(L, R, rson);
174     } else if (R <= mid) {
175         return query4(L, R, lson);
176     } else {
177         ret = max(
178             query4(L, R, lson),
179             query4(L, R, rson)
180         );
181         int rc1 = nd[rt<<1].rc1;
182         int lc1 = nd[rt<<1|1].lc1;
183         if (rc1 > mid-L+1)
184             rc1 = mid-L+1;
185         if (lc1 > R-mid)
186             lc1 = R-mid;
187         ret = max(
188             rc1 + lc1,
189             ret
190         );
191     }
192     return ret;
193 }
194 
195 int main() {
196     int i, j, k;
197     int a, b;
198     
199     #ifndef ONLINE_JUDGE
200         freopen("data.in", "r", stdin);
201         freopen("data.out", "w", stdout);
202     #endif
203     
204     scanf("%d", &t);
205     while (t--) {
206         scanf("%d %d", &n, &m);
207         build(1, n, 1);
208         while (m--) {
209             scanf("%d %d %d", &op, &a, &b);
210             ++a;
211             ++b;
212             if (op == 0) {
213                 update1(a, b, 1, n, 1);
214             } else if (op == 1) {
215                 update1(a, b, 1, n, 1);
216             } else if (op == 2) {
217                 update2(a, b, 1, n, 1);
218             } else if (op == 3) {
219                 k = query3(a, b, 1, n, 1);
220                 printf("%d\n", k);
221             } else {
222                 k = query4(a, b, 1, n, 1);
223                 printf("%d\n", k);
224             }
225         }
226     }
227     
228     return 0;
229 }

 

posted on 2015-04-06 17:31  Bombe  阅读(189)  评论(0编辑  收藏  举报

导航