HDU 3911 Black And White (线段树区间合并 + lazy标记)

时间:2021-07-22 20:14:32

题目链接: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异或一次,异或两次就说明操作抵消了。然后就是细心点就好了。

 #include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 1e5 + ;
struct SegTree {
int l , r , lazy;
int lsum1 , rsum1 , sum1;
int lsum0 , rsum0 , sum0;
}T[MAXN << ];
int a[MAXN]; void Pushdown(int p) {
if(T[p].lazy) {
int ls = p << , rs = (p << )|;
T[ls].lazy ^= T[p].lazy;
T[rs].lazy ^= T[p].lazy;
int temp = T[ls].lsum1;
T[ls].lsum1 = T[ls].lsum0;
T[ls].lsum0 = temp;
temp = T[ls].rsum1;
T[ls].rsum1 = T[ls].rsum0;
T[ls].rsum0 = temp;
temp = T[ls].sum1;
T[ls].sum1 = T[ls].sum0;
T[ls].sum0 = temp; temp = T[rs].lsum1;
T[rs].lsum1 = T[rs].lsum0;
T[rs].lsum0 = temp;
temp = T[rs].rsum1;
T[rs].rsum1 = T[rs].rsum0;
T[rs].rsum0 = temp;
temp = T[rs].sum1;
T[rs].sum1 = T[rs].sum0;
T[rs].sum0 = temp; T[p].lazy = ;
}
} void Pushup(int p) {
T[p].lsum1 = T[p << ].lsum1 , T[p].lsum0 = T[p << ].lsum0;
T[p].rsum1 = T[(p << )|].rsum1 , T[p].rsum0 = T[(p << )|].rsum0;
if(T[p].lsum1 == T[p << ].r - T[p << ].l + )
T[p].lsum1 += T[(p << )|].lsum1;
if(T[p].rsum1 == T[(p << )|].r - T[(p << )|].l + )
T[p].rsum1 += T[p << ].rsum1;
if(T[p].lsum0 == T[p << ].r - T[p << ].l + )
T[p].lsum0 += T[(p << )|].lsum0;
if(T[p].rsum0 == T[(p << )|].r - T[(p << )|].l + )
T[p].rsum0 += T[p << ].rsum0;
T[p].sum1 = max(T[p << ].sum1 , max(T[(p << )|].sum1 , T[p << ].rsum1 + T[(p << )|].lsum1));
T[p].sum0 = max(T[p << ].sum0 , max(T[(p << )|].sum0 , T[p << ].rsum0 + T[(p << )|].lsum0));
} void build(int p , int l , int r) {
int mid = (l + r) >> ;
T[p].lazy = ;
T[p].l = l , T[p].r = r;
if(l == r) {
scanf("%d" , a + l);
T[p].sum1 = T[p].lsum1 = T[p].rsum1 = a[l] ? : ;
T[p].sum0 = T[p].lsum0 = T[p].rsum0 = a[l] ? : ;
return ;
}
build(p << , l , mid);
build((p << )| , mid + , r);
Pushup(p);
} void updata(int p , int l , int r , int flag) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == l && T[p].r == r) {
T[p].lazy ^= flag;
int temp = T[p].lsum1;
T[p].lsum1 = T[p].lsum0;
T[p].lsum0 = temp;
temp = T[p].rsum1;
T[p].rsum1 = T[p].rsum0;
T[p].rsum0 = temp;
temp = T[p].sum1;
T[p].sum1 = T[p].sum0;
T[p].sum0 = temp;
return ;
}
Pushdown(p);
if(r <= mid) {
updata(p << , l , r , flag);
}
else if(l > mid) {
updata((p << )| , l , r , flag);
}
else {
updata(p << , l , mid , flag);
updata((p << )| , mid + , r , flag);
}
Pushup(p);
} int query(int p , int l , int r) {
int mid = (T[p].l + T[p].r) >> ;
if(T[p].l == l && T[p].r == r) {
return T[p].sum1;
}
Pushdown(p);
if(r <= mid) {
return query(p << , l , r);
}
else if(l > mid) {
return query((p << )| , l , r);
}
else {
return max( min(T[p << ].rsum1 , mid - l + )+min(T[(p << )|].lsum1 , r - mid) , //mid在l和r之间
max( query(p << , l , mid) , query((p << )| , mid + , r)) );
}
} int main()
{
int n , m , choose , u , v;
while(~scanf("%d" , &n)) {
build( , , n);
scanf("%d" , &m);
while(m--) {
scanf("%d %d %d" , &choose , &u , &v);
if(choose) {
updata( , u , v , );
}
else {
printf("%d\n" , query( , u , v));
}
}
}
return ;
}