hdu3911——Black And White (线段树区间合并)

Time limit
3000 ms
Memory limit
32768 kB
There are a bunch of stones on the beach; Stone color is white or black. Little Sheep has a magic brush, she can change the color of a continuous stone, black to white, white to black. Little Sheep like black very much, so she want to know the longest period of consecutive black stones in a range [i, j].

Input

 There are multiple cases, the first line of each case is an integer n(1<= n <= 10^5), followed by n integer 1 or 0(1 indicates black stone and 0 indicates white stone), then is an integer M(1<=M<=10^5) followed by M operations formatted as x i j(x = 0 or 1) , x=1 means change the color of stones in range[i,j], and x=0 means ask the longest period of consecutive black stones in range[i,j]

Output

When x=0 output a number means the longest length of black stones in range [i,j].

Sample Input

4
1 0 1 0
5
0 1 4
1 2 3
0 1 4
1 3 3
0 4 4

Sample Output

1
2
0

题解:

线段树区间合并裸题。注意要保存最长连续0,方便进行改变时直接01互换就行了。

代码:

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 100005;
int Data[MAXN];
int Change[MAXN*4];

struct D{
	int l1;
	int l0;
	int r1;
	int r0;
	int max1;
	int max0;
	int s;
}Tree[MAXN*4];

void Up(int temp){
	Tree[temp].l1 = Tree[temp<<1].l1;
	if(Tree[temp<<1].l1 == Tree[temp<<1].s)Tree[temp].l1 += Tree[temp<<1|1].l1;
	Tree[temp].r1 = Tree[temp<<1|1].r1;
	if(Tree[temp<<1|1].r1 == Tree[temp<<1|1].s)Tree[temp].r1 += Tree[temp<<1].r1;
	Tree[temp].l0 = Tree[temp<<1].l0;
	if(Tree[temp<<1].l0 == Tree[temp<<1].s)Tree[temp].l0 += Tree[temp<<1|1].l0;
	Tree[temp].r0 = Tree[temp<<1|1].r0;
	if(Tree[temp<<1|1].r0 == Tree[temp<<1|1].s)Tree[temp].r0 += Tree[temp<<1].r0;
	Tree[temp].max1 = max(Tree[temp<<1].max1,Tree[temp<<1|1].max1);
	Tree[temp].max1 = max(Tree[temp].max1,Tree[temp<<1].r1+Tree[temp<<1|1].l1);
	Tree[temp].max0 = max(Tree[temp<<1].max0,Tree[temp<<1|1].max0);
	Tree[temp].max0 = max(Tree[temp].max0,Tree[temp<<1].r0+Tree[temp<<1|1].l0);
}

void Build(int temp,int left,int right){
	Tree[temp].s = right-left+1;
	if(left == right){
		if(Data[left]){
			Tree[temp].l1 = Tree[temp].r1 = Tree[temp].max1 = 1;
			Tree[temp].l0 = Tree[temp].r0 = Tree[temp].max0 = 0;
		}else {
			Tree[temp].l1 = Tree[temp].r1 = Tree[temp].max1 = 0;
			Tree[temp].l0 = Tree[temp].r0 = Tree[temp].max0 = 1;
		}
		return ;
	}
	int mid = left + (right-left)/2;
	Build(temp<<1,left,mid);
	Build(temp<<1|1,mid+1,right);
	Up(temp);
}

void PushDown(int temp){
	if(Change[temp]){
		Change[temp<<1] ^= 1;
		Change[temp<<1|1] ^= 1;
		swap(Tree[temp<<1].l1,Tree[temp<<1].l0);
		swap(Tree[temp<<1].r1,Tree[temp<<1].r0);
		swap(Tree[temp<<1].max1,Tree[temp<<1].max0);
		swap(Tree[temp<<1|1].l1,Tree[temp<<1|1].l0);
		swap(Tree[temp<<1|1].r1,Tree[temp<<1|1].r0);
		swap(Tree[temp<<1|1].max1,Tree[temp<<1|1].max0);
		Change[temp] = 0;
	}
}

void Updata(int temp,int left,int right,int ql,int qr){
	if(ql<=left && qr>=right){
		Change[temp] ^= 1;
		swap(Tree[temp].l1,Tree[temp].l0);
		swap(Tree[temp].r1,Tree[temp].r0);
		swap(Tree[temp].max1,Tree[temp].max0);
		return ;
	}
	
	PushDown(temp);
	
	int mid = left + (right-left)/2;
	if(ql<=mid)Updata(temp<<1,left,mid,ql,qr);
	if(qr>mid)Updata(temp<<1|1,mid+1,right,ql,qr);
	
	Up(temp);
} 

int query(int temp,int left,int right,int ql,int qr){
	if(ql==left && qr==right)return Tree[temp].max1;
	
	PushDown(temp);
	
	int mid = left + (right-left)/2;
	if(qr<=mid)return query(temp<<1,left,mid,ql,qr);
	else if(ql>mid)return query(temp<<1|1,mid+1,right,ql,qr);
	else {
		int a,b,c;
		a = query(temp<<1,left,mid,ql,mid);
		b = query(temp<<1|1,mid+1,right,mid+1,qr);
		c = min(mid-ql+1,Tree[temp<<1].r1) + min(qr-mid,Tree[temp<<1|1].l1);
		return max(a,max(b,c));
	}
}

 
int main(){
	
	int N,M;
	while(scanf("%d",&N)!=EOF){
		for(int i=1 ; i<=N ; i++){
			scanf("%d",&Data[i]);
		}
		memset(Change,0,sizeof(Change));
		Build(1,1,N);
		scanf("%d",&M);
		int A,B,C;
		while(M--){
			scanf("%d %d %d",&A,&B,&C);
			if(A){
				Updata(1,1,N,B,C);
			}else {
				printf("%d\n",query(1,1,N,B,C));
			}
		}
	}
	
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值