HDU 3397 线段树区间染色 区间查询

九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/12223079

题意:

t个测试数据

n 个数 m个操作

下面n个数的当前颜色(只有 0 1 两种 )

oper [u,v]

oper==0  区间染0色

oper==1 区间染1色

oper==2 区间反色

oper==3 问区间1色个数

oper==4 问区间 连续1色个数

代码写搓了:

 

#include<iostream>   
#include<stdio.h>   
#include<string>   
#include<string.h>   
#include<algorithm>   
#include<set>   
#include <cstdio>     
#include <cstring>     
#include <iostream>     
#include <math.h>     
#include <queue>     
#define N 1001000
#define ll int     
#define L(x) x<<1     
#define R(x) x<<1|1     
#define Mid(x,y) (x+y)>>1     
using namespace std;    
inline ll Min(ll a,ll b){return a>b?b:a;}  
inline ll Max(ll a,ll b){return a>b?a:b;}  
int a[N];//1是黑   

struct node{    
	int l,r;    
	int Win, Bin;//区间内黑白的最长   
	int Llen, Rlen;// Llen 是 这个区间内 从区间左端点向右连续相同颜色的长度   
	int Lc, Rc;//左端颜色   

	int lazy;  

	int len(){return r-l+1;}  
	int onenum;
}tree[N];    

void change_other(int id,int oper){
tree[id].Llen = tree[id].Rlen = tree[id].len();
	if(oper == 1)//全改0
	{
		tree[id].Bin = tree[id].Lc = tree[id].Rc = 0;  
		tree[id].Win = tree[id].len();
		tree[id].onenum = 0;

	}
	if(oper == 2)//全改1
	{
		tree[id].Lc = tree[id].Rc = 1;  
		tree[id].onenum = tree[id].Bin = tree[id].len();
		tree[id].Win = 0;


	}
	tree[id].lazy = 0;
	tree[L(id)].lazy = tree[R(id)].lazy = oper;

}
void Lazy(int id){  
	if(!tree[id].lazy)  
		return ;  
	if(tree[id].lazy == 3)
	{
		tree[id].Lc ^= 1;  
		tree[id].Rc ^= 1;  
		int temp = tree[id].Win;    tree[id].Win = tree[id].Bin; tree[id].Bin = temp;  
		tree[id].onenum = tree[id].len() - tree[id].onenum;
		if(tree[L(id)].lazy == 3)    tree[L(id)].lazy = 0;
		else { Lazy(L(id));  tree[L(id)].lazy =3; }

		if(tree[R(id)].lazy == 3)    tree[R(id)].lazy = 0;
		else { Lazy(R(id));  tree[R(id)].lazy =3; }


	}

	if(tree[id].lazy == 1){
		tree[id].Bin = tree[id].Lc = tree[id].Rc = 0;  
		tree[id].Win = tree[id].Llen = tree[id].Rlen = tree[id].len();
		tree[id].onenum = 0;
		tree[L(id)].lazy = tree[R(id)].lazy = 1;

	}
	if(tree[id].lazy == 2){
		tree[id].Lc = tree[id].Rc = 1;  
		tree[id].onenum = tree[id].Bin = tree[id].Llen = tree[id].Rlen = tree[id].len();
		tree[id].Win = 0;

		tree[L(id)].lazy = tree[R(id)].lazy = 2;

	}
	tree[id].lazy = 0;  

}  
void change(int id){  

	tree[id].Lc ^= 1;  
	tree[id].Rc ^= 1;  
	int temp = tree[id].Win;    tree[id].Win = tree[id].Bin; tree[id].Bin = temp;  
	tree[id].onenum = tree[id].len() - tree[id].onenum;
	if(tree[L(id)].lazy == 3)tree[L(id)].lazy = 0;
	else {Lazy(L(id)); tree[L(id)].lazy = 3;}

	if(tree[R(id)].lazy == 3)tree[R(id)].lazy = 0;
	else {Lazy(R(id)); tree[R(id)].lazy = 3;}
}  
void updata_up(int id){  
	if(tree[id].l == tree[id].r) return ;
	Lazy(L(id)),    Lazy(R(id));  
	tree[id].Lc = tree[L(id)].Lc , tree[id].Rc = tree[R(id)].Rc ;  
	tree[id].Rlen = tree[R(id)].Rlen;  
	tree[id].Llen = tree[L(id)].Llen;  

	tree[id].Bin=Max(tree[L(id)].Bin, tree[R(id)].Bin);  
	tree[id].Win=Max(tree[L(id)].Win, tree[R(id)].Win);  

	if( tree[L(id)].Rc == tree[R(id)].Lc)  
	{  
		if(tree[L(id)].Rc)  
			tree[id].Bin = Max(tree[id].Bin, tree[L(id)].Rlen + tree[R(id)].Llen);  
		else   
			tree[id].Win = Max(tree[id].Win, tree[L(id)].Rlen + tree[R(id)].Llen);  

		if(tree[L(id)].Llen == tree[L(id)].len())  
			tree[id].Llen = tree[L(id)].len() + tree[R(id)].Llen;  
		if(tree[R(id)].Rlen == tree[R(id)].len())  
			tree[id].Rlen = tree[R(id)].len() + tree[L(id)].Rlen;  
	}  

	if(tree[id].Lc==1)tree[id].Bin=Max(tree[id].Bin, tree[id].Llen);  
	else tree[id].Win=Max(tree[id].Win, tree[id].Llen);  

	if(tree[id].Rc==1)tree[id].Bin=Max(tree[id].Bin, tree[id].Rlen);  
	else tree[id].Win=Max(tree[id].Win, tree[id].Rlen); 	

	tree[id].onenum = tree[L(id)].onenum + tree[R(id)].onenum;
}  
void build(int l,int r,int id){  
	tree[id].l = l, tree[id].r = r;  
	tree[id].lazy=0;  
	if(l == r){  
		tree[id].Llen=tree[id].Rlen=1;  

		tree[id].Lc = tree[id].Rc = a[l];  
		tree[id].Bin = a[l];  
		tree[id].Win = 1-a[l];  
		tree[id].onenum = a[l];
		return ;  
	}
	int mid = Mid(l,r);  
	build( l, mid, L(id));        
	build( mid+1, r, R(id));  
	updata_up(id);  
}  

void updata(int l, int r, int id){  
Lazy(id);
	if(l == tree[id].l && tree[id].r == r)  
	{ change(id); return ;}  

	int mid=Mid(tree[id].l, tree[id].r);  

	if(r <= mid)     updata(l, r, L(id));  
	else if(mid < l) updata(l, r, R(id));  
	else {  
		updata(l, mid, L(id));  
		updata(mid+1, r, R(id));  
	}  
	updata_up(id);  
}  
void updata_other(int l, int r, int id,int oper){  
	Lazy(id);
	if(l == tree[id].l && tree[id].r == r)  
	{change_other(id,oper);  return ;}  

	int mid=Mid(tree[id].l, tree[id].r);  

	if(r <= mid)     updata_other(l, r, L(id),oper);  
	else if(mid < l) updata_other(l, r, R(id),oper);  
	else {  
		updata_other(l, mid, L(id),oper);  
		updata_other(mid+1, r, R(id),oper);  
	}  
	updata_up(id);  
}  
int query(int l, int r, int id){  
	Lazy(id);  
	if(l == tree[id].l && tree[id].r == r)  
		return tree[id].Bin;   

	int mid=Mid(tree[id].l, tree[id].r);  
	int r1=0, r2=0, ans=0;  
	if(r <= mid) r1 = query(l, r, L(id));  
	else if(mid < l)  r2 = query(l, r, R(id));  
	else {  
		r1 = query(l, mid, L(id));  
		r2 = query(mid+1, r, R(id));  

		if(tree[L(id)].Rc == 1 && tree[R(id)].Lc == 1)  
			ans = Min(mid-l+1, tree[L(id)].Rlen) + Min(r-mid, tree[R(id)].Llen) ;  
		r1 = Max(ans, r1);  
	}  
	ans = Max(r1, r2);  
	return ans;  
}  
int query_one(int l, int r, int id){  
	Lazy(id);  
	if(l == tree[id].l && tree[id].r == r)  
		return tree[id].onenum;   

	int mid=Mid(tree[id].l, tree[id].r);  
	int r1=0, r2=0;  
	if(r <= mid) r1 = query_one(l, r, L(id));  
	else if(mid < l)  r2 = query_one(l, r, R(id));  
	else {  
		r1 = query_one(l, mid, L(id));  
		r2 = query_one(mid+1, r, R(id));  
	}  
	return r1+r2;  
} 
int main(){  
	int n, que, oper, b, c,T;scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&que);
		for(int i=1;i<=n;i++)scanf("%d", &a[i]);  
		build(1,n,1);  

		while(que--)  
		{  
			scanf("%d %d %d", &oper, &b, &c);  
			oper++,b++,c++;
			if(oper==3)  
				updata(b,c,1);  
			else if(oper<=2)
				updata_other(b,c,1,oper);

			else
			{
				if(oper==4)
					printf("%d\n",query_one(b,c,1));
				if(oper==5)
					printf("%d\n", query(b,c,1));//问黑色   
			}

		}  
	}  
	return 0;  
}  
/*
1
10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5

2 2 2
4 0 4

0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9

0 0 0 1 1 0 1 0 1 1

1 1 1 1 1 0 1 0 1 1  1 3  改1
1 1 0 1 1 0 1 0 1 1  3 3  换
1 1 0 0 0 0 0 0 1 1  4 7  改0
1 1 0 1 1 1 1 1 1 1  4 8  换  there
1 1 1 1 1 1 1 1 1 1  1 6  改1
1 1 1 1 1 0 0 1 1 1  6 7  改0

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值