原题传送:http://acm.hdu.edu.cn/showproblem.php?pid=3397
线段树,区间合并。
节点记录的信息如下:
int l, r, c; // 区间左端点,右端点,长度
int lsum1, rsum1, msum1; // 左连续1长度,右连续1长度,区间最长连续1长度
int lsum0, rsum0, msum0; // 左连续0长度,右连续0长度,区间最长连续0长度
int sum; // 区间1的个数
题目许多更新询问操作都是比较熟悉的了。
这道题对于01反转操作我是这样做的:从上面列出来的节点信息可以看到,既记录了区间1的情况,也记录了区间0的情况,当得到反转命令时就很容易进行转换(把1和0的情况互换即可)。
这道题还有一点要注意的,就是对于lazy标记更新时,如果得到的命令是0或1,那么区间lazy标记直接变为0或1即可,但对于lazy为2的反转命令的情况需要进行这样的处理:如果当前lazy标记为0,则变为1;如果为1,则变为0;如果为2,则取消标记变为-1;如果为-1,则赋予标记为2。(这个情况没处理好导致自己花了好长时间。)
代码一如既往的饱满。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 #include <string.h> 3 #define lson (cur << 1) 4 #define rson (cur << 1 | 1) 5 #define N 100100 6 7 struct node 8 { 9 int l, r, c; // 区间左端点,右端点,长度 10 int lsum1, rsum1, msum1; // 左连续1长度,右连续1长度,区间最长连续1长度 11 int lsum0, rsum0, msum0; // 左连续0长度,右连续0长度,区间最长连续0长度 12 int sum; // 区间1的个数 13 }tree[N << 2]; 14 15 int lazy[N << 2], a[N], n, m; 16 17 inline int max(int x, int y){return x > y ? x : y;} 18 inline int min(int x, int y){return x < y ? x : y;} 19 20 void transform(int rt) 21 { 22 int x, y, z; 23 x = tree[rt].lsum1; 24 y = tree[rt].rsum1; 25 z = tree[rt].msum1; 26 tree[rt].lsum1 = tree[rt].lsum0; 27 tree[rt].rsum1 = tree[rt].rsum0; 28 tree[rt].msum1 = tree[rt].msum0; 29 tree[rt].lsum0 = x; 30 tree[rt].rsum0 = y; 31 tree[rt].msum0 = z; 32 tree[rt].sum = tree[rt].c - tree[rt].sum; 33 34 if(lazy[rt] == 0) // 弄清lazy标记的传递 35 lazy[rt] = 1; 36 else if(lazy[rt] == 1) 37 lazy[rt] = 0; 38 else if(lazy[rt] == 2) 39 lazy[rt] = -1; 40 else if(lazy[rt] == -1) 41 lazy[rt] = 2; 42 } 43 44 void pushdown(int cur) 45 { 46 if(lazy[cur] == 0) 47 { 48 lazy[lson] = lazy[rson] = lazy[cur]; 49 tree[lson].lsum1 = tree[lson].rsum1 = tree[lson].msum1 = 0; 50 tree[rson].lsum1 = tree[rson].rsum1 = tree[rson].msum1 = 0; 51 tree[lson].lsum0 = tree[lson].rsum0 = tree[lson].msum0 = tree[lson].c; 52 tree[rson].lsum0 = tree[rson].rsum0 = tree[rson].msum0 = tree[rson].c; 53 tree[lson].sum = 0; 54 tree[rson].sum = 0; 55 } 56 else if(lazy[cur] == 1) 57 { 58 lazy[lson] = lazy[rson] = lazy[cur]; 59 tree[lson].lsum1 = tree[lson].rsum1 = tree[lson].msum1 = tree[lson].c; 60 tree[rson].lsum1 = tree[rson].rsum1 = tree[rson].msum1 = tree[rson].c; 61 tree[lson].lsum0 = tree[lson].rsum0 = tree[lson].msum0 = 0; 62 tree[rson].lsum0 = tree[rson].rsum0 = tree[rson].msum0 = 0; 63 tree[lson].sum = tree[lson].c; 64 tree[rson].sum = tree[rson].c; 65 } 66 else if(lazy[cur] == 2) 67 { 68 transform(lson); 69 transform(rson); 70 } 71 lazy[cur] = -1; 72 } 73 74 void pushup(int cur) 75 { 76 tree[cur].sum = tree[lson].sum + tree[rson].sum; 77 78 tree[cur].lsum1 = tree[lson].lsum1; 79 tree[cur].rsum1 = tree[rson].rsum1; 80 tree[cur].msum1 = max(tree[lson].msum1, tree[rson].msum1); 81 if(tree[lson].lsum1 == tree[lson].c) 82 tree[cur].lsum1 += tree[rson].lsum1; 83 if(tree[rson].rsum1 == tree[rson].c) 84 tree[cur].rsum1 += tree[lson].rsum1; 85 tree[cur].msum1 = max(tree[cur].msum1, tree[lson].rsum1 + tree[rson].lsum1); 86 87 tree[cur].lsum0 = tree[lson].lsum0; 88 tree[cur].rsum0 = tree[rson].rsum0; 89 tree[cur].msum0 = max(tree[lson].msum0, tree[rson].msum0); 90 if(tree[lson].lsum0 == tree[lson].c) 91 tree[cur].lsum0 += tree[rson].lsum0; 92 if(tree[rson].rsum0 == tree[rson].c) 93 tree[cur].rsum0 += tree[lson].rsum0; 94 tree[cur].msum0 = max(tree[cur].msum0, tree[lson].rsum0 + tree[rson].lsum0); 95 } 96 97 void update(int cur, int l, int r, int flag) 98 { 99 if(tree[cur].l >= l && tree[cur].r <= r) 100 { 101 if(flag == 0) 102 { 103 lazy[cur] = 0; 104 tree[cur].lsum1 = tree[cur].rsum1 = tree[cur].msum1 = 0; 105 tree[cur].lsum0 = tree[cur].rsum0 = tree[cur].msum0 = tree[cur].c; 106 tree[cur].sum = 0; 107 } 108 else if(flag == 1) 109 { 110 lazy[cur] = 1; 111 tree[cur].lsum1 = tree[cur].rsum1 = tree[cur].msum1 = tree[cur].c; 112 tree[cur].lsum0 = tree[cur].rsum0 = tree[cur].msum0 = 0; 113 tree[cur].sum = tree[cur].c; 114 } 115 else if(flag == 2) 116 { 117 transform(cur); 118 } 119 return ; 120 } 121 pushdown(cur); 122 int mid = (tree[cur].l + tree[cur].r) >> 1; 123 if(mid >= l) 124 update(lson, l, r, flag); 125 if(mid + 1 <= r) 126 update(rson, l, r, flag); 127 pushup(cur); 128 } 129 130 void query3(int cur, int l, int r, int &ans) 131 { 132 if(tree[cur].l >= l && tree[cur].r <= r) 133 { 134 ans += tree[cur].sum; 135 return ; 136 } 137 pushdown(cur); 138 int mid = (tree[cur].l + tree[cur].r) >> 1; 139 if(mid >= l) 140 query3(lson, l, r, ans); 141 if(mid + 1 <= r) 142 query3(rson, l, r, ans); 143 } 144 145 int query4(int cur, int l, int r) 146 { 147 if(tree[cur].l >= l && tree[cur].r <= r) 148 { 149 return tree[cur].msum1; 150 } 151 pushdown(cur); 152 int ans = 0; 153 int mid = (tree[cur].l + tree[cur].r) >> 1; 154 if(mid >= l) 155 ans = max(ans, query4(lson, l, r)); 156 if(mid < r) 157 ans = max(ans, query4(rson, l, r)); 158 ans = max(ans, min(mid - l + 1, tree[lson].rsum1) + min(r - mid, tree[rson].lsum1)); 159 return ans; 160 } 161 162 163 void build(int cur, int l, int r) 164 { 165 tree[cur].l = l, tree[cur].r = r, tree[cur].c = r - l + 1; 166 lazy[cur] = -1; 167 if(l == r) 168 { 169 if(a[l] == 1) 170 { 171 tree[cur].lsum1 = tree[cur].rsum1 = tree[cur].msum1 = 1; 172 tree[cur].lsum0 = tree[cur].rsum0 = tree[cur].msum0 = 0; 173 tree[cur].sum = 1; 174 } 175 else if(a[l] == 0) 176 { 177 tree[cur].lsum1 = tree[cur].rsum1 = tree[cur].msum1 = 0; 178 tree[cur].lsum0 = tree[cur].rsum0 = tree[cur].msum0 = 1; 179 tree[cur].sum = 0; 180 } 181 return ; 182 } 183 int mid = (l + r) >> 1; 184 build(lson, l, mid); 185 build(rson, mid + 1, r); 186 pushup(cur); 187 } 188 189 int main() 190 { 191 int i, cas, op, x, y, ans; 192 scanf("%d", &cas); 193 while(cas --) 194 { 195 scanf("%d%d", &n, &m); 196 for(i = 1; i <= n; i ++) 197 scanf("%d", &a[i]); 198 build(1, 1, n); 199 while(m --) 200 { 201 scanf("%d%d%d", &op, &x, &y); 202 ++x, ++y; 203 switch(op) 204 { 205 case 0: 206 update(1, x, y, 0); 207 break; 208 case 1: 209 update(1, x, y, 1); 210 break; 211 case 2: 212 update(1, x, y, 2); 213 break; 214 case 3: 215 ans = 0; 216 query3(1, x, y, ans); 217 printf("%d\n", ans); 218 break; 219 case 4: 220 printf("%d\n", query4(1, x, y)); 221 break; 222 default: 223 break; 224 } 225 } 226 } 227 return 0; 228 }