再做一道线段树。
http://acm.hdu.edu.cn/showproblem.php?pid=3397
这题还是很有意义的,其特殊之处在于操作2和操作4.
操作2是0变1,1变0,这样在pushdown的时候就不能简单覆盖下去,因为如果孩子节点有操作没有完成,会导致结果错误。但是又不能遇到操作2就把子节点也pushdown,这样会超时。。。需要想点办法。。。所以观察一下操作2的效果,可以得出如下结论:
当字节点操作未做操作为1时,将操作2pushdown下来等同于将字节点进行0操作
同理,字节点未做操作为0时,等同于1操作;当字节点未做操作为2时,等同于什么也不做;字节点没有未做操作时,直接覆盖即可。
这样就解决了操作2的pushdown问题。
接下来解决操作4的问题:求最长的连续1的长度。
这个问题和以前做过的“内存分配”问题类似,最长连续1的来源有三种:
左子树,右子树或跨左右子树中间的一段。
因此,在线段树节点中还需要记录该节点包含最左边的连续1的长度/包含最右边的连续1的长度。
为了操作方便,在线段树节点上还记录了对应得0的个数,这样在进行操作2时只需简单进行一下值交换即可。
另外还需要注意的一点是节点上包含的连续1长度可能会大于查询的范围,此处应注意一下。
1 //5931624 2012-05-12 10:24:25 Accepted 3397 953MS 10944K 5137 B C++ nkhelloworld 2 //5931486 2012-05-12 10:05:33 Accepted 3397 1578MS 11208K 6639 B G++ nkhelloworld 3 #include <cstdio> 4 #include <iostream> 5 #include <cstring> 6 using namespace std; 7 8 #define MAXN 110000 9 int n,m; 10 int a[MAXN]; 11 12 struct SEGTREE 13 { 14 int l,r,num,len1,len0,lsublen1,rsublen1,lsublen0,rsublen0,op; 15 }tree[MAXN*4]; 16 17 void refresh(int root) 18 { 19 tree[root].num = tree[root<<1].num + tree[root<<1|1].num; 20 21 tree[root].len1 = max(tree[root<<1].len1, max(tree[root<<1|1].len1, 22 tree[root<<1].rsublen1+tree[root<<1|1].lsublen1)); 23 tree[root].len0 = max(tree[root<<1].len0, max(tree[root<<1|1].len0, 24 tree[root<<1].rsublen0 + tree[root<<1|1].lsublen0)); 25 26 tree[root].lsublen1 = tree[root<<1].lsublen1; 27 if(tree[root].lsublen1 == tree[root<<1].r - tree[root<<1].l + 1) 28 tree[root].lsublen1 += tree[root<<1|1].lsublen1; 29 30 tree[root].rsublen1 = tree[root<<1|1].rsublen1; 31 if(tree[root].rsublen1 == tree[root<<1|1].r - tree[root<<1|1].l + 1) 32 tree[root].rsublen1 += tree[root<<1].rsublen1; 33 34 tree[root].lsublen0 = tree[root<<1].lsublen0; 35 if(tree[root].lsublen0 == tree[root<<1].r - tree[root<<1].l + 1) 36 tree[root].lsublen0 += tree[root<<1|1].lsublen0; 37 38 tree[root].rsublen0 = tree[root<<1|1].rsublen0; 39 if(tree[root].rsublen0 == tree[root<<1|1].r - tree[root<<1|1].l + 1) 40 tree[root].rsublen0 += tree[root<<1].rsublen0; 41 } 42 43 void buildsegtree(int root,int l,int r) 44 { 45 tree[root].l = l; tree[root].r = r; 46 tree[root].op = -1; 47 if(l == r) 48 { 49 tree[root].num = a[l]; 50 tree[root].len1 = tree[root].lsublen1 51 = tree[root].rsublen1 = a[l]?1:0; 52 tree[root].len0 = tree[root].lsublen0 53 = tree[root].rsublen0 = a[l]?0:1; 54 return ; 55 } 56 int mid = (l+r)>>1; 57 buildsegtree(root<<1,l,mid); 58 buildsegtree(root<<1|1,mid+1,r); 59 refresh(root); 60 } 61 62 void pushdown(int root) 63 { 64 if(tree[root].op == -1) return ; 65 if(tree[root].l != tree[root].r) 66 { 67 if(tree[root].op == 2) 68 { 69 switch(tree[root<<1].op) 70 { 71 case -1: tree[root<<1].op = 2; break; 72 case 0: tree[root<<1].op = 1; break; 73 case 1: tree[root<<1].op = 0; break; 74 case 2: tree[root<<1].op = -1; break; 75 } 76 switch(tree[root<<1|1].op) 77 { 78 case -1: tree[root<<1|1].op = 2; break; 79 case 0: tree[root<<1|1].op = 1; break; 80 case 1: tree[root<<1|1].op = 0; break; 81 case 2: tree[root<<1|1].op = -1; break; 82 } 83 84 } 85 else 86 tree[root<<1].op = tree[root<<1|1].op = tree[root].op; 87 } 88 if(tree[root].op == 0) 89 { 90 tree[root].num 91 = tree[root].len1 92 = tree[root].lsublen1 93 = tree[root].rsublen1 94 = 0; 95 tree[root].len0 96 = tree[root].lsublen0 97 = tree[root].rsublen0 98 = tree[root].r - tree[root].l + 1; 99 } 100 else if(tree[root].op == 1) 101 { 102 tree[root].num 103 = tree[root].len1 104 = tree[root].lsublen1 105 = tree[root].rsublen1 106 = tree[root].r - tree[root].l + 1; 107 tree[root].len0 108 = tree[root].lsublen0 109 = tree[root].rsublen0 110 = 0; 111 } 112 else 113 { 114 tree[root].num = tree[root].r - tree[root].l + 1 - tree[root].num; 115 swap(tree[root].len0,tree[root].len1); 116 swap(tree[root].lsublen1,tree[root].lsublen0); 117 swap(tree[root].rsublen1,tree[root].rsublen0); 118 } 119 tree[root].op = -1; 120 } 121 122 int query_num(int root,int l,int r) 123 { 124 pushdown(root); 125 if(tree[root].l == l && tree[root].r == r) 126 return tree[root].num; 127 int mid = (tree[root].l + tree[root].r)>>1; 128 if(r <= mid) 129 return query_num(root<<1,l,r); 130 else if(l > mid) 131 return query_num(root<<1|1,l,r); 132 else 133 return query_num(root<<1,l,mid) + query_num(root<<1|1,mid+1,r); 134 } 135 136 int query_lenth(int root,int l,int r) 137 { 138 pushdown(root); 139 if(tree[root].l == l && tree[root].r == r) 140 return tree[root].len1; 141 int mid = (tree[root].l + tree[root].r)>>1; 142 if(r <= mid) 143 return query_lenth(root<<1,l,r); 144 else if(l > mid) 145 return query_lenth(root<<1|1,l,r); 146 else 147 { 148 pushdown(root<<1); 149 pushdown(root<<1|1); 150 int ret = max(query_lenth(root<<1,l,mid), 151 query_lenth(root<<1|1,mid+1,r)); 152 int lchild1 = tree[root<<1].rsublen1; 153 if(lchild1 > mid-l+1) lchild1 = mid-l+1; 154 int rchild1 = tree[root<<1|1].lsublen1; 155 if(rchild1 > r-mid) rchild1 = r-mid; 156 return max(ret,lchild1+rchild1); 157 } 158 159 } 160 161 void update(int root,int l,int r,int op) 162 { 163 pushdown(root); 164 if(tree[root].l == l && tree[root].r == r) 165 { 166 tree[root].op = op; 167 return ; 168 } 169 int mid = (tree[root].l + tree[root].r)>>1; 170 if(r<=mid) 171 update(root<<1,l,r,op); 172 else if(l > mid) 173 update(root<<1|1,l,r,op); 174 else 175 { 176 update(root<<1,l,mid,op); 177 update(root<<1|1,mid+1,r,op); 178 } 179 pushdown(root<<1); 180 pushdown(root<<1|1); 181 refresh(root); 182 } 183 184 int main() 185 { 186 int i,j,totcase; 187 scanf("%d",&totcase); 188 while(totcase--) 189 { 190 scanf("%d%d",&n,&m); 191 for(i=1;i<=n;i++) 192 { 193 scanf("%d",&a[i]); 194 } 195 buildsegtree(1,1,n); 196 int op,a,b; 197 while(m--) 198 { 199 scanf("%d%d%d",&op,&a,&b); 200 a++; b++; 201 if(op<=2) 202 { 203 update(1,a,b,op); 204 } 205 else if(op==3) 206 { 207 printf("%d\n",query_num(1,a,b)); 208 } 209 else 210 printf("%d\n",query_lenth(1,a,b)); 211 } 212 } 213 return 0; 214 }