您的位置:首页 > 其它

HDU 3911 Black And White

2011-09-24 20:47 471 查看

Black And White

Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1278 Accepted Submission(s): 445


[align=left]Problem Description[/align]
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].

[align=left]Input[/align]
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]

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

[align=left]Sample Input[/align]

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

[align=left]Sample Output[/align]

1
2
0

本题的题意是对于N个点0代表白色,1代表黑色,一次操作可以使i~j的每个点有0->1,1->0,题目给出初始化的状态,要求操作之后i~j之间连续的最大的黑色线段的长度;
很明显要用线段树,考虑到对与同一段线段两次更新后,想当与没有更新,所以可以用延迟标记优化;
考虑到要线段相加和取反,故添加 int b,w; //最大连续的黑色和白色的个数
int lval,rval;//与左右端点相同的连续颜色的个数
int lc,rc; //左右端点的颜色来记录一个线段的状态;哎,自己做不出来,水平不够呀。。看的别人的代码,在加上自己的体会

#include<stdio.h>
#include<string.h>
#define N 100500
#define Max(a,b) (((a)>(b))?(a):(b))
#define Min(a,b) (((a)<(b))?(a):(b))
struct node
{
int l,r,cover,tag;
int b,w; //最大连续的黑色和白色的个数
int lval,rval;//与左右端点相同的连续颜色的个数
int lc,rc; //左右端点的颜色
int calmid()
{
return (l+r)>>1;
}
}b[4*N];
int a
;
void update(int i)
{
b[i].b=Max(b[i+i].b,b[i+i+1].b);
b[i].w=Max(b[i+i].w,b[i+i+1].w);
b[i].lval=b[i+i].lval;
b[i].rval=b[i+i+1].rval;
if(b[i+i].rc==b[i+i+1].lc)
if(b[i+i].rc==1)
b[i].b=Max(b[i].b,b[i+i].rval+b[i+i+1].lval);
else
b[i].w=Max(b[i].w,b[i+i].rval+b[i+i+1].lval);
if(b[i+i].cover!=-1&&b[i+i+1].lc==b[i+i].cover)
b[i].lval+=b[i+i+1].lval;
if(b[i+i+1].cover!=-1&&b[i+i].rc==b[i+i+1].cover)
b[i].rval+=b[i+i].rval;
b[i].lc=b[i+i].lc;b[i].rc=b[i+i+1].rc;
if(b[i+i].cover==b[i+i+1].cover)
b[i].cover=b[i+i].cover;
else
b[i].cover=-1;
}

void build(int i,int l,int r)
{
b[i].l=l;b[i].r=r;
b[i].cover=-1;
b[i].tag=0;//开始没有延迟
b[i].lc=b[i].rc=-1;
b[i].b=b[i].w=0;
b[i].lval=b[i].rval=0;
if(l==r)
{
b[i].lc=b[i].rc=a[l];
if(a[l]==1)
{
b[i].b=1;
b[i].cover=1;
}
else
{
b[i].w=1;
b[i].cover=0;
}
b[i].lval=b[i].rval=1;
return ;
}
int mid=(l+r)>>1;
build(i+i,l,mid);
build(i+i+1,mid+1,r);
update(i);
}
void samp(int i)
{
int t;
t=b[i].b,b[i].b=b[i].w,b[i].w=t;
b[i].lc=b[i].lc^1;
b[i].rc=b[i].rc^1;
if(b[i].cover!=-1)
b[i].cover=b[i].cover^1;
}
void update(int i,int l,int r)
{
if(l<=b[i].l&&b[i].r<=r)
{
samp(i);
b[i].tag=b[i].tag^1;//在这没有向下更新
return ;
}
if(b[i].tag)//如果延迟了,并且递归到这一层,要向下更新
{
samp(i+i);samp(i+i+1);
b[i+i].tag=b[i+i].tag^1;b[i+i+1].tag=b[i+i+1].tag^1;
b[i].tag=0;
}
int mid=b[i].calmid();
if(l<=mid)
update(i+i,l,r);
if(r>mid)
update(i+i+1,l,r);
update(i);
}

int query(int i,int l,int r)
{

int ans;
if(l==b[i].l&&b[i].r==r)
return b[i].b;
if(b[i].tag)
{
samp(i+i+1);samp(i+i);
b[i+i].tag=b[i+i].tag^1;
b[i+i+1].tag=b[i+i+1].tag^1;
b[i].tag=0;
}
int mid=b[i].calmid();
if(r<=mid)
ans=query(i+i,l,r);
else if(l>mid)
ans=query(i+i+1,l,r);
else
{
int lb=query(i+i,l,mid);
int rb=query(i+i+1,mid+1,r);
ans=Max(lb,rb);
if(b[i+i].rc==1&&b[i+i+1].lc==1)
ans=Max(ans,Min(mid-l+1,b[i+i].rval)+Min(r-mid,b[i+i+1].lval));
// ans=Max(ans,b[i+i].rval+b[i+i+1].lval);//一直错在这里
if(ans>r-l+1)
ans=r-l+1;
}
update(i);
return ans;
}

int main()
{
int n,m,i,tag,l,r;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&m);
for(i=0;i<m;i++)
{
scanf("%d%d%d",&tag,&l,&r);
if(tag==0)
{
int ans=query(1,l,r);
printf("%d\n",ans);
}
else
update(1,l,r);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: