【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 }