HDU 3911 Black And White (线段树区间合并 + lazy标记)
Posted Recoder
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3911 Black And White (线段树区间合并 + lazy标记)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3911
给你n个数0和1,m个操作:
0操作 输出l到r之间最长的连续1的个数
1操作 将l到r之间的0变1,1变0
区间合并的模版题,结构体中的lsum1表示从此区间最左端开始连续1的个数,rsum1表示从此区间最右端开始连续1的个数,sum1表示此区间连续1的个数最长是多少。lsum0,rsum0,sum0也是如此。每一次1的操作将区间内lazy标记与1异或一次,异或两次就说明操作抵消了。然后就是细心点就好了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 const int MAXN = 1e5 + 5; 6 struct SegTree { 7 int l , r , lazy; 8 int lsum1 , rsum1 , sum1; 9 int lsum0 , rsum0 , sum0; 10 }T[MAXN << 2]; 11 int a[MAXN]; 12 13 void Pushdown(int p) { 14 if(T[p].lazy) { 15 int ls = p << 1 , rs = (p << 1)|1; 16 T[ls].lazy ^= T[p].lazy; 17 T[rs].lazy ^= T[p].lazy; 18 int temp = T[ls].lsum1; 19 T[ls].lsum1 = T[ls].lsum0; 20 T[ls].lsum0 = temp; 21 temp = T[ls].rsum1; 22 T[ls].rsum1 = T[ls].rsum0; 23 T[ls].rsum0 = temp; 24 temp = T[ls].sum1; 25 T[ls].sum1 = T[ls].sum0; 26 T[ls].sum0 = temp; 27 28 temp = T[rs].lsum1; 29 T[rs].lsum1 = T[rs].lsum0; 30 T[rs].lsum0 = temp; 31 temp = T[rs].rsum1; 32 T[rs].rsum1 = T[rs].rsum0; 33 T[rs].rsum0 = temp; 34 temp = T[rs].sum1; 35 T[rs].sum1 = T[rs].sum0; 36 T[rs].sum0 = temp; 37 38 T[p].lazy = 0; 39 } 40 } 41 42 void Pushup(int p) { 43 T[p].lsum1 = T[p << 1].lsum1 , T[p].lsum0 = T[p << 1].lsum0; 44 T[p].rsum1 = T[(p << 1)|1].rsum1 , T[p].rsum0 = T[(p << 1)|1].rsum0; 45 if(T[p].lsum1 == T[p << 1].r - T[p << 1].l + 1) 46 T[p].lsum1 += T[(p << 1)|1].lsum1; 47 if(T[p].rsum1 == T[(p << 1)|1].r - T[(p << 1)|1].l + 1) 48 T[p].rsum1 += T[p << 1].rsum1; 49 if(T[p].lsum0 == T[p << 1].r - T[p << 1].l + 1) 50 T[p].lsum0 += T[(p << 1)|1].lsum0; 51 if(T[p].rsum0 == T[(p << 1)|1].r - T[(p << 1)|1].l + 1) 52 T[p].rsum0 += T[p << 1].rsum0; 53 T[p].sum1 = max(T[p << 1].sum1 , max(T[(p << 1)|1].sum1 , T[p << 1].rsum1 + T[(p << 1)|1].lsum1)); 54 T[p].sum0 = max(T[p << 1].sum0 , max(T[(p << 1)|1].sum0 , T[p << 1].rsum0 + T[(p << 1)|1].lsum0)); 55 } 56 57 void build(int p , int l , int r) { 58 int mid = (l + r) >> 1; 59 T[p].lazy = 0; 60 T[p].l = l , T[p].r = r; 61 if(l == r) { 62 scanf("%d" , a + l); 63 T[p].sum1 = T[p].lsum1 = T[p].rsum1 = a[l] ? 1 : 0; 64 T[p].sum0 = T[p].lsum0 = T[p].rsum0 = a[l] ? 0 : 1; 65 return ; 66 } 67 build(p << 1 , l , mid); 68 build((p << 1)|1 , mid + 1 , r); 69 Pushup(p); 70 } 71 72 void updata(int p , int l , int r , int flag) { 73 int mid = (T[p].l + T[p].r) >> 1; 74 if(T[p].l == l && T[p].r == r) { 75 T[p].lazy ^= flag; 76 int temp = T[p].lsum1; 77 T[p].lsum1 = T[p].lsum0; 78 T[p].lsum0 = temp; 79 temp = T[p].rsum1; 80 T[p].rsum1 = T[p].rsum0; 81 T[p].rsum0 = temp; 82 temp = T[p].sum1; 83 T[p].sum1 = T[p].sum0; 84 T[p].sum0 = temp; 85 return ; 86 } 87 Pushdown(p); 88 if(r <= mid) { 89 updata(p << 1 , l , r , flag); 90 } 91 else if(l > mid) { 92 updata((p << 1)|1 , l , r , flag); 93 } 94 else { 95 updata(p << 1 , l , mid , flag); 96 updata((p << 1)|1 , mid + 1 , r , flag); 97 } 98 Pushup(p); 99 } 100 101 int query(int p , int l , int r) { 102 int mid = (T[p].l + T[p].r) >> 1; 103 if(T[p].l == l && T[p].r == r) { 104 return T[p].sum1; 105 } 106 Pushdown(p); 107 if(r <= mid) { 108 return query(p << 1 , l , r); 109 } 110 else if(l > mid) { 111 return query((p << 1)|1 , l , r); 112 } 113 else { 114 return max( min(T[p << 1].rsum1 , mid - l + 1)+min(T[(p << 1)|1].lsum1 , r - mid) , //mid在l和r之间 115 max( query(p << 1 , l , mid) , query((p << 1)|1 , mid + 1 , r)) ); 116 } 117 } 118 119 int main() 120 { 121 int n , m , choose , u , v; 122 while(~scanf("%d" , &n)) { 123 build(1 , 1 , n); 124 scanf("%d" , &m); 125 while(m--) { 126 scanf("%d %d %d" , &choose , &u , &v); 127 if(choose) { 128 updata(1 , u , v , 1); 129 } 130 else { 131 printf("%d\n" , query(1 , u , v)); 132 } 133 } 134 } 135 return 0; 136 }
以上是关于HDU 3911 Black And White (线段树区间合并 + lazy标记)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 3911 Black and White (线段树,区间翻转)
[HDOJ3911]Black And White(线段树,区间合并)
HDU 5113--Black And White(搜索+剪枝)