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
- nbut线段树线段树专题S - Black And White
- HDU--3911[Black And White] 线段树
- hdu 3911 Black And White 线段树
- HDU 3911 Black And White 线段树
- hdu 3911 Black And White(线段树)
- nbut线段树专题C - Mayor\'s posters
- hdu 3911 Black And White 区间合并 线段树
- hdu 3911 Black And White(线段树)
- HDU 3911 Black And White(线段树区间合并)
- hdu 3911 Black And White 线段树区间合并
- hdu3911 Black And White(线段树区间合并)
- HDU 3911 Black And White (线段树区间更新)
- HDOJ 3911 Black And White 【线段树 区间合并】
- hdu3911 Black And White 线段树区间合并
- hdu3911 Black And White 【线段树+区间异或操作】
- hdu 3911 black and white 线段树区间合并
- hdu 3911 Black and White 线段树维护01序列
- hdu 3911 Black And White (线段树)
- nbut线段树专题M - Buy Tickets
- nbut线段树专题 J - Atlantis
- 我对离散化的一些感悟
- nbut线段树专题A - Count the Colors
- nbut线段树专题A - Count the Colors
- nbut线段树线段树专题S - Black And White
- NBUT-2014暑期集训专题练习1 -> 二分法 N - N
- nbut线段树专题P - Hotel
- nbut线段树专题Q - Tunnel Warfare
- 如何观看Netflix的美国
- WhatsApp发布安卓手表客户端 手表聊天时代来了
- apt命令
- NBUT动态规划专题——D - The more, The Better
- NBUT 动态规划专题C - 滑雪