nbut线段树线段树专题S - Black And White

来源:互联网 发布:完美告白知乎 编辑:程序博客网 时间:2024/06/05 22:12

Description

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].
 

典型的区间合并问题,具体操作在pushup上



#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>

using namespace std;
const int maxn = 100010;
bool color[maxn];
struct node
{
int l,r,ls_one,ls_zero,rs_one,rs_zero,add,all_one,all_zero;//用1表示黑色,0表示白色
}tree[maxn<<2];//ls_one,ls_zero,rs_one,rs_zero,all_one,all_zero分别表示从左边数连续1的个数,
//从左边数连续0的个数,从右边数连续1的个数,连续0的个数,这段区间上最大连续1的个数,最大连续0的个数

void pushup(int p)
{
int l_len=(tree[p<<1].r-tree[p<<1].l+1);//计算左右区间的长度
int r_len=(tree[p<<1|1].r-tree[p<<1|1].l+1);
tree
[p].ls_one=tree[p<<1].ls_one;//左儿子的ls_one显然是父亲节点ls_one的一部分
if(tree[p<<1].ls_one==l_len)//如果左二子全是1,加上右儿子的那一部分
tree
[p].ls_one+=tree[p<<1|1].ls_one;
tree
[p].rs_one=tree[p<<1|1].rs_one;//同理
if(tree[p<<1|1].rs_one==r_len)
tree
[p].rs_one+=tree[p<<1].rs_one;
//计算最大长度时是这样的,要么是左儿子的最大值,右儿子的最大值,或者是左儿子右边的+右儿子左边的,三者的最大值 tree
[p].all_one=max(max(tree[p<<1].all_one,tree[p<<1|1].all_one),tree[p<<1].rs_one+tree[p<<1|1].ls_one);
tree
[p].ls_zero=tree[p<<1].ls_zero;
if(tree[p<<1].ls_zero==l_len)
tree
[p].ls_zero+=tree[p<<1|1].ls_zero;
tree
[p].rs_zero=tree[p<<1|1].rs_zero;
if(tree[p<<1|1].rs_zero==r_len)
tree
[p].rs_zero+=tree[p<<1].rs_zero;
tree
[p].all_zero=max(max(tree[p<<1].all_zero,tree[p<<1|1].all_zero),tree[p<<1].rs_zero+tree[p<<1|1].ls_zero);
}

void pushdown(int p)
{
if(tree[p].add==1)//延迟更新子节点,
{
tree
[p<<1].add^=1;//由于子树的线段是由父亲树继承过来的,那么子树的左右儿子也要更新,例如p<<1的add也是1,那么就是说,本来他的子树就要更新,现在也要对他更新,0-1-0,等于没变
tree
[p<<1|1].add^=1;//所以异或以后,本来是1的,现在不用更新,相反是0的,更新下去
tree
[p].add=0;
swap(tree[p<<1].ls_one,tree[p<<1].ls_zero);//0 1反转,所以1 0的所有信息交换
swap(tree[p<<1].rs_one,tree[p<<1].rs_zero);
swap(tree[p<<1].all_one,tree[p<<1].all_zero);
swap(tree[p<<1|1].ls_one,tree[p<<1|1].ls_zero);
swap(tree[p<<1|1].rs_one,tree[p<<1|1].rs_zero);
swap(tree[p<<1|1].all_one,tree[p<<1|1].all_zero);
}
}
void build(int p,int l,int r)
{
tree
[p].l=l;
tree
[p].r=r;
tree
[p].add=0;
if(l==r)
{
if(color[l]==1)
{
tree
[p].ls_one=1;
tree
[p].rs_one=1;
tree
[p].all_one=1;
tree
[p].ls_zero=0;
tree
[p].rs_zero=0;
tree
[p].all_zero=0;
}
else
{
tree
[p].ls_one=0;
tree
[p].rs_one=0;
tree
[p].all_one=0;
tree
[p].ls_zero=1;
tree
[p].rs_zero=1;
tree
[p].all_zero=1;
}
return ;
}
int mid=(l+r)>>1;
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
pushup(p);
}

void update(int p,int l,int r)
{
if(l==tree[p].l && r==tree[p].r)
{
tree
[p].add^=1;//原本是0的,现在为1,用来down的,//原来是1的,现在为0,就和上面一样,本来就要更新,现在又要更新,更新两次等于没更新
swap(tree[p].ls_one,tree[p].ls_zero);
swap(tree[p].rs_one,tree[p].rs_zero);
swap(tree[p].all_one,tree[p].all_zero);
return ;
}
pushdown(p);
int mid=(tree[p].l + tree[p].r)>>1;
if(r<=mid)
update(p<<1,l,r);
else if(l>mid)
update(p<<1|1,l,r);
else
{
update(p<<1,l,mid);
update(p<<1|1,mid+1,r);
}
pushup(p);
}

int query(int p,int l,int r)
{
if(l==tree[p].l && r==tree[p].r)
{
return tree[p].all_one;
}
pushdown(p);
int mid=(tree[p].l + tree[p].r)>>1;
if(r<=mid)
return query(p<<1,l,r);
else if(l>mid)
return query(p<<1|1,l,r);
else
{
int lm,rm;
lm
=query(p<<1,l,mid);
rm
=query(p<<1|1,mid+1,r);
int a=tree[p<<1].rs_one;
int b=tree[p<<1|1].ls_one;
if(a>tree[p<<1].r-l+1)//区间被划分为[l,tree[p<<1].r],[tree[p<<1|1].l,r],那么a,b当然不可能超过各自所在区间长度。
a
=tree[p<<1].r-l+1;
if(b>r-tree[p<<1|1].l+1)
b
=r-tree[p<<1|1].l+1;
return max(max(lm,rm),a+b);
}
}


int main()
{
int n,m;
int a=1,b=2;
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
scanf("%d",&color[i]);
scanf("%d",&m);
build(1,1,n);
int x,y,t;
while(m--)
{
scanf("%d%d%d",&t,&x,&y);
if(t==0)
{
printf("%d\n",query(1,x,y));
}
else
{
update(1,x,y);
}
}
}
return 0;
}


0 0
原创粉丝点击