程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> HDU 3911 Black And White(線段樹區間合並)

HDU 3911 Black And White(線段樹區間合並)

編輯:C++入門知識

HDU 3911 Black And White(線段樹區間合並)


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
線段樹區間合並:對於每個區間[l,r]所對應的rs,我們給出6個量: lmax_1:左起的1的最大前綴,lmax_0:左起的0的最大前綴; rmax_1:右起的1的最大後綴rmax_0:右起的0的最大後綴; max_1:區間的1的最大連續值,max_0:區間的0的最大連續值 我們的任務就是不斷地更新求值。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define CLEAR( a , x ) memset ( a , x , sizeof a )
typedef long long LL;
typedef pairpil;
const int mod = 1000000007;
const int maxn=1e5+10;
int lmax_1[maxn<<2],rmax_1[maxn<<2];
int lmax_0[maxn<<2],rmax_0[maxn<<2];
int max_1[maxn<<2],max_0[maxn<<2];
int col[maxn<<2];
int n,m,os;
void pushup(int rs,int m)
{
    lmax_1[rs]=lmax_1[rs<<1];//處理左邊一類前綴
    lmax_0[rs]=lmax_0[rs<<1];
    if(lmax_1[rs<<1]==m-(m>>1))  lmax_1[rs]+=lmax_1[rs<<1|1];
    if(lmax_0[rs<<1]==m-(m>>1))  lmax_0[rs]+=lmax_0[rs<<1|1];

    rmax_1[rs]=rmax_1[rs<<1|1];//處理右邊一類後綴
    rmax_0[rs]=rmax_0[rs<<1|1];
    if(rmax_1[rs<<1|1]==(m>>1))  rmax_1[rs]+=rmax_1[rs<<1];
    if(rmax_0[rs<<1|1]==(m>>1))  rmax_0[rs]+=rmax_0[rs<<1];

    max_1[rs]=max(max_1[rs<<1],max_1[rs<<1|1]);//處理整個區間的值
    max_1[rs]=max(max_1[rs],rmax_1[rs<<1]+lmax_1[rs<<1|1]);
    max_0[rs]=max(max_0[rs<<1],max_0[rs<<1|1]);
    max_0[rs]=max(max_0[rs],rmax_0[rs<<1]+lmax_0[rs<<1|1]);
}
void work(int rs)
{
    swap(lmax_1[rs],lmax_0[rs]);
    swap(rmax_1[rs],rmax_0[rs]);
    swap(max_1[rs],max_0[rs]);
}
void push_down(int rs)
{
    if(col[rs])
    {
        col[rs<<1]^=1;col[rs<<1|1]^=1;
        col[rs]=0;work(rs<<1);work(rs<<1|1);
    }
}
void build(int rs,int l,int r)
{
    col[rs]=0;
    if(l==r)
    {
        scanf("%d",&os);
        if(os==1)
        {
            lmax_1[rs]=rmax_1[rs]=max_1[rs]=1;
            lmax_0[rs]=rmax_0[rs]=max_0[rs]=0;
        }
        else
        {
            lmax_1[rs]=rmax_1[rs]=max_1[rs]=0;
            lmax_0[rs]=rmax_0[rs]=max_0[rs]=1;
        }
        return ;
    }
    int mid=(l+r)>>1;
    build(rs<<1,l,mid);
    build(rs<<1|1,mid+1,r);
    pushup(rs,r-l+1);
}
void update(int x,int y,int l,int r,int rs)
{
    if(l>=x&&r<=y)
    {
        col[rs]^=1;
        work(rs);//交換值
        return ;
    }
    push_down(rs);
    int mid=(l+r)>>1;
    if(x<=mid)  update(x,y,l,mid,rs<<1);
    if(y>mid)  update(x,y,mid+1,r,rs<<1|1);
    pushup(rs,r-l+1);
}
int query(int x,int y,int l,int r,int rs)
{
    if(l>=x&&r<=y)
        return max_1[rs];
    push_down(rs);
    int mid=(l+r)>>1;
    if(x>mid)  return query(x,y,mid+1,r,rs<<1|1);
    if(y<=mid)  return query(x,y,l,mid,rs<<1);
    int t1=query(x,y,l,mid,rs<<1);
    int t2=query(x,y,mid+1,r,rs<<1|1);
    int r1=min(mid-x+1,rmax_1[rs<<1]);//以mid為分割點
    int r2=min(y-mid,lmax_1[rs<<1|1]);
    int res=max(max(t1,t2),r1+r2);
    return res;
}
int main()
{
    int op,x,y;
    while(~scanf("%d",&n))
    {
       build(1,1,n);
       scanf("%d",&m);
       while(m--)
       {
           scanf("%d%d%d",&op,&x,&y);
           if(op==1)
               update(x,y,1,n,1);
           else
               printf("%d\n",query(x,y,1,n,1));
       }
    }
    return 0;
}


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved