Black And White

Black And White

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


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

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
 
/超时算法/
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAX 500000
typedef struct infor
{
	int left , right , value ; 
}infor ; 
infor tree[4*MAX] ; 
int a[MAX+1] ;
void create(int root , int left , int right)
{
	tree[root].left = left ; 
	tree[root].right = right ; 
	if( right == left )
	{
		tree[root].value = a[right] ; 
		return ;
	}
	int mid = (left + right ) / 2 ;
	create(root*2 , left , mid );
	create(root*2 + 1 , mid + 1 , right );
	//	tree[root].value = tree[root*2].value + tree[root*2 + 1].value ;  
}
void update(int root , int left , int right , int  l , int r )
{
	if(left == right )
	{
		if(tree[root].value == 0 )
			tree[root].value = 1 ;
		else
			tree[root].value = 0 ;
		return ;
	}
	int mid = (tree[root].left + tree[root].right ) / 2 ;
	if(l > mid )
		update(root*2 + 1, mid + 1 , right , l , r );
	else if(r <= mid )
		update(root*2 , left , mid , l , r );
	else
	{
		update(root*2 , left , mid ,  l , r );
		update(root*2 + 1 , mid + 1 , right , l , r );
	}
	
	//tree[root].value =(tree[root*2].value + tree[root*2 + 1].value ) ;
}
int sum  ,max1; 
void cal(int root , int left , int right , int l , int r)
{
	if(left == right)
	{
		if(tree[root].value == 1){
			sum ++ ; 
			return ;
		}
		else{
			max1 = max1 < sum ? sum : max1 ; 
			sum = 0 ; 
			return ;
		}
		//return tree[root].value ;
	}
	int mid = (tree[root].left + tree[root].right ) / 2;
	if(l > mid )
		cal(root*2 + 1 , mid + 1 , right , l , r );
	else if(r <= mid )
		cal(root*2 , left , mid , l , r );
	else {
		cal(root*2 , left , mid , l , r ) ;
		cal(root*2 + 1 , mid + 1 , right , l , r ) ; 
	}
}
int main( void )
{
	int n , i ;
	cin >> n ;
	for( i = 1 ; i <= n ; i ++)
		scanf("%d",&a[i]);
	create(1,1,n);
	int q;
	cin >> q ; 
	while(q --)
	{
		int m , x , y ;
		while(scanf("%d %d %d",&m,&x,&y)!=EOF){
			if(m==0){
				sum = 0 ; 
				max1 = 0 ;
				cal(1,1,n,x,y);
				//printf("%d\n",cal(1,1,n,x,y));
				printf("%d\n",max1);
			}
			else
				update(1,1,n,x,y);
		}
	}
	return 0;
}


 /*还是超时算法,(*^__^*) 嘻嘻……*/
#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 100000
typedef struct infor
{
    int l , r;    //l左孩子,r右孩子
    int llen, rlen , len ;    //llen从左边起最长黑石头序列,rlen右边起黑石头个数,最长黑石头个数
    int lnum , rnum ,cnt ;//lnum最左边的石头颜色, 最右边的石头颜色
}infor ;
infor t[4*MAX] ;
int a[MAX + 1] ;
int max(int b , int c)
{
    return b>c?b:c ;
}
int min(int b , int c)
{
    return b>c?c:b ;
}
void up(int rt , int lenl , int lenr)
{
    t[rt].len = max(t[rt*2].len , t[rt*2 + 1 ].len);
    t[rt].llen = t[rt*2].llen ;
    t[rt].rlen = t[rt*2 + 1].rlen ;
    if(t[rt*2].rnum == 1 && t[rt*2 +1 ].lnum== 1)
    {
        t[rt].len = max(t[rt].len , t[rt*2].rlen + t[rt*2 + 1].llen);
        if(t[rt*2].llen >= lenl)    
            t[rt].llen +=t[rt*2 + 1].llen ;
        if(t[rt*2 + 1].rlen >= lenr)
            t[rt].rlen +=t[rt*2].rlen ;
    }
}
void create(int rt , int l , int r)
{
    t[rt].l = l ;
    t[rt].r = r ;
    t[rt].cnt = 0 ;
    if( l == r )
    {
        if(a[l]==1)
        {
            t[rt].len = 1 ;t[rt].llen = 1;t[rt].rlen = 1;t[rt].lnum = 1 ;t[rt].rnum = 1;
        }
        else
        {
            t[rt].len = 0 ;t[rt].llen = 0;t[rt].rlen = 0;t[rt].lnum = 0 ;t[rt].rnum = 0;
        }
        return ;
    }
    int mid = (l + r) / 2 ; 
    create(rt*2 , l , mid );
    create(rt*2 + 1 , mid + 1 , r );
    t[rt].lnum = t[rt*2].lnum;
    t[rt].rnum = t[rt*2 + 1 ].rnum ;
    up(rt , mid - l + 1 , r - mid );
}
void update(int rt , int l , int r , int x , int y)
{
    if(t[rt].l == t[rt].r )
    {
        if(t[rt].lnum ==1)
        {
            t[rt].lnum = 0 ;t[rt].rnum = 0 ;t[rt].len = 0;t[rt].llen = 0 ;t[rt].rlen = 0 ;
        }
        else
        {
            t[rt].lnum = 1 ;t[rt].rnum = 1 ;t[rt].len = 1;t[rt].rlen = 1;t[rt].llen = 1 ;
        }
        return ;
    }
    int mid = (t[rt].l + t[rt].r) / 2 ;
    if(t[rt].cnt)
    {
        up(rt , mid - l + 1 , r - mid );
        t[rt].cnt = 0 ;
    }
    if(x>mid)
        update(rt*2 + 1 , mid + 1 , r , x , y);
    else if(y<= mid)
        update(rt*2 , l , mid , x , y );
    else
    {
        update(rt*2 , l , mid , x , y );
        update(rt*2 + 1 , mid + 1 , r , x , y );
    }
    t[rt].lnum = t[rt*2].lnum;
    t[rt].rnum = t[rt*2 + 1 ].rnum ;
    up(rt , mid - l + 1 , r - mid );

}
int cal(int rt , int l , int r , int x , int y)
{
    if(x<=l && y>=r)
        return t[rt].len ;
    int mid = (t[rt].l + t[rt].r ) / 2 ; 
    if(x > mid )
        return cal(rt*2 + 1 , mid + 1 , r , x , y );
    else if(y<=mid)
        return cal(rt*2 , l , mid , x , y );
    int ret = max(cal(rt*2 + 1 , mid + 1 , r , x , y),cal(rt*2 , l , mid , x , y ));
    if(t[rt*2 + 1].lnum== 1 && t[rt*2].rnum == 1)
        return ret=max(ret , min(y, mid + t[rt*2 + 1 ].llen ) - max(x , mid - t[rt*2].rlen + 1) + 1);
    return ret ;
}
int main(void )
{
    int n , i ;
    cin>>n ; 
    for( i = 1; i <= n ; i ++)
        scanf("%d",&a[i]);
    create( 1 , 1, n );
    int m ; 
    scanf("%d",&m);
    while(m--)
    {
        int val , x , y; 
        scanf("%d %d %d",&val , &x , &y);
        if(val==1)
            update( 1 , 1 , n, x, y);
        else
            printf("%d\n",cal(1 , 1, n, x, y));
    }
    return 0;
}
/注:转载/
#include<stdio.h>
struct haha
{
 int left;
 int right;
 int l_b;//、 lb表示区间从左边开始连续的1的个数   如当前区间为1-10 那么这个就代表包含1的最长1串
 int r_b;//、 rb表示区间从右边开始连续的1的个数   如当前区间为1-10 那么这个就代表包含10的最长1串
 int l_w;//、 lw表示区间从左边开始连续的0的个数
 int r_w;//、 rw表示区间从右边开始连续的0的个数
 int maxb;
 int maxw;
 int cnt;
 /*cnt表示区间被访问的次数,这里利用它实现lazy思xiang
  这里简述一下lazy思想:每次访问的时候不用都更新到最低层的元线段,每次只访问到恰好的区间,
 在这里设一个标志,表示这次更新只访问到了该区间!那么当再次访问该区间的时候就需要将该标志往其子区间传递*/
}tree[100000*4];
int max(int a,int b)
{
 if(a>b) return a;
 else return b;
}
int min(int a,int b)
{
 if(a<b) return a;
 else return b;
}
void update(int nd)
{
 int left_len,right_len;
 tree[nd].maxb=max(max(tree[nd*2].maxb,tree[nd*2+1].maxb),tree[nd*2].r_b+tree[nd*2+1].l_b);
    tree[nd].maxw=max(max(tree[nd*2].maxw,tree[nd*2+1].maxw),tree[nd*2].r_w+tree[nd*2+1].l_w);
 left_len=tree[nd*2].right-tree[nd*2].left+1; right_len=tree[nd*2+1].right-tree[nd*2+1].left+1;
 tree[nd].l_b=tree[nd*2].l_b;    if(tree[nd*2].l_b==left_len) tree[nd].l_b+=tree[nd*2+1].l_b;
 tree[nd].l_w=tree[nd*2].l_w;    if(tree[nd*2].l_w==left_len) tree[nd].l_w+=tree[nd*2+1].l_w;
 tree[nd].r_b=tree[nd*2+1].r_b;  if(tree[nd*2+1].r_b==right_len) tree[nd].r_b+=tree[nd*2].r_b;
 tree[nd].r_w=tree[nd*2+1].r_w;  if(tree[nd*2+1].r_w==right_len) tree[nd].r_w+=tree[nd*2].r_w;
}
void build(int nd,int left,int right)
{
 int mid,num;
 tree[nd].left=left;tree[nd].right=right; tree[nd].cnt=0;
 if(left==right)
 {
  scanf("%d",&num);
  if(num)
  {tree[nd].maxb=tree[nd].l_b=tree[nd].r_b=1; tree[nd].maxw=tree[nd].l_w=tree[nd].r_w=0; }
  else
  {tree[nd].maxw=tree[nd].l_w=tree[nd].r_w=1; tree[nd].maxb=tree[nd].l_b=tree[nd].r_b=0; }
  return;
 }
 mid=(left+right)/2;
 build(nd*2,left,mid);
 build(nd*2+1,mid+1,right);//是mid+1  RUNTIEM ERROR 了好几次
 update(nd);
}
void change(int nd)
{
      int temp;
   temp=tree[nd].l_b;tree[nd].l_b=tree[nd].l_w;tree[nd].l_w=temp;
   temp=tree[nd].maxb;tree[nd].maxb=tree[nd].maxw;tree[nd].maxw=temp;
   temp=tree[nd].r_b;tree[nd].r_b=tree[nd].r_w;tree[nd].r_w=temp;
   tree[nd].cnt=!tree[nd].cnt;
}
void  update2(int nd,int left,int right)
{
 int mid;
 if(tree[nd].left==left&&tree[nd].right==right)
 {
           change(nd);
     return ;
 }
 if(tree[nd].cnt) {change(nd*2);change(nd*2+1);tree[nd].cnt=0;}
 mid=(tree[nd].left+tree[nd].right)/2;
 if(right<=mid) update2(nd*2,left,right);
 else if(left>mid) update2(nd*2+1,left,right);
 else {update2(nd*2,left,mid);update2(nd*2+1,mid+1,right);}//是mid+1  RUNTIEM ERROR 了好几次
 update(nd);
}
int query(int nd,int left,int right)
{
     int mid,lr,rr;
  if(tree[nd].left==left&&tree[nd].right==right)
   return tree[nd].maxb;
  if(tree[nd].cnt) {change(nd*2);change(nd*2+1);tree[nd].cnt=0;}
  mid=(tree[nd].right+tree[nd].left)/2;
  if(right<=mid) return query(nd*2,left,right);
  else if(left>mid)return query(nd*2+1,left,right);
  else
  {
   lr=query(nd*2,left,mid);
   rr=query(nd*2+1,mid+1,right);
   return max(max(min(tree[nd*2].r_b,lr)+min(tree[nd*2+1].l_b,rr),lr),rr);//这句话真心不懂啊!
 //  return max(max(tree[nd*2].r_b+tree[nd*2+1].l_b,lr),rr);
  }
}
int main()
{
 int n,i,opr,m,left,right;
 while(scanf("%d",&n)!=EOF)
 {
  build(1,1,n);
  scanf("%d",&m);
  for(i=1;i<=m;i++)
  {
   scanf("%d %d %d",&opr,&left,&right);
   if(opr) update2(1,left,right);
   else printf("%d\n",query(1,left,right));
  }
 }
 return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值