//HDOJ 3911 Black And White 線段樹 區間合併 成段更新
/*
題意:有一堆黑、白球排成一排,有兩種操作:
1:將一段連續的球改變顏色,黑色變成白色,白色變成黑色
2:查詢一段區間內連續的黑色的球的個數
思路:每個結點記錄7個信息:
lsum0:從左端開始的連續的白球個數
rsum0:從右端開始的連續的白球個數
msum0:區間內連續的白球的最大個數
lsum1:從左端開始的連續的黑球個數
rsum1:從右端開始的連續的黑球個數
msum1:區間內連續的黑球的最大個數
add:是否向下更新
進行操作1的時候只要將黑球白球的各種信息交換
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define N 100005
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
int n,m;
int lsum0[N<<2],rsum0[N<<2],msum0[N<<2];
int lsum1[N<<2],rsum1[N<<2],msum1[N<<2];
int sum[N<<2],add[N<<2];
int Max(int x,int y){
return x>y?x:y;
}
void swap(int &x,int &y){
int tmp = x;
x = y;
y = tmp;
}
void Pushup(int rt,int m){
lsum0[rt] = lsum0[rt<<1];
rsum0[rt] = rsum0[rt<<1|1];
if(lsum0[rt] == m-(m>>1)) lsum0[rt] += lsum0[rt<<1|1];
if(rsum0[rt] == (m >> 1)) rsum0[rt] += rsum0[rt<<1];
msum0[rt] = Max(rsum0[rt<<1]+lsum0[rt<<1|1],Max(msum0[rt<<1],msum0[rt<<1|1]));
lsum1[rt] = lsum1[rt<<1];
rsum1[rt] = rsum1[rt<<1|1];
if(lsum1[rt] == m-(m>>1)) lsum1[rt] += lsum1[rt<<1|1];
if(rsum1[rt] == (m >> 1)) rsum1[rt] += rsum1[rt<<1];
msum1[rt] = Max(rsum1[rt<<1]+lsum1[rt<<1|1],Max(msum1[rt<<1],msum1[rt<<1|1]));
}
void Pushdown(int rt){
if(add[rt]){
add[rt<<1] ^= 1;
add[rt<<1|1] ^= 1;
swap(lsum0[rt<<1],lsum1[rt<<1]);
swap(rsum0[rt<<1],rsum1[rt<<1]);
swap(msum0[rt<<1],msum1[rt<<1]);
swap(lsum0[rt<<1|1],lsum1[rt<<1|1]);
swap(rsum0[rt<<1|1],rsum1[rt<<1|1]);
swap(msum0[rt<<1|1],msum1[rt<<1|1]);
add[rt] = 0;
}
}
void Build(int rt,int l,int r){
if(l == r){
int x;
scanf("%d",&x);
lsum1[rt] = rsum1[rt] = msum1[rt]= x;
lsum0[rt] = rsum0[rt] = msum0[rt] = 1-x;
return ;
}
int mid = (l + r) >> 1;
Build(lson);
Build(rson);
Pushup(rt,r-l+1);
}
void Update(int rt,int l,int r,int L,int R){
if(L <= l && R >= r){
swap(lsum0[rt],lsum1[rt]);
swap(rsum0[rt],rsum1[rt]);
swap(msum0[rt],msum1[rt]);
add[rt]^=1;
return ;
}
Pushdown(rt);
int mid = (l + r) >> 1;
if(L <= mid) Update(lson,L,R);
if(R > mid ) Update(rson,L,R);
Pushup(rt,r-l+1);
}
int Query(int rt,int l,int r,int L,int R){
if(L <= l && R >= r){
return msum1[rt];
}
Pushdown(rt);
int s1=0,s2=0,s3=0;
int mid = (l + r) >> 1;
if(L <= mid) s1 = Query(lson,L,R);
if(R > mid ) s2 = Query(rson,L,R);
if(L <= mid && R > mid){
if(rsum1[rt<<1] <= mid-L+1) s3 += rsum1[rt<<1];
else s3 += mid-L+1;
if(lsum1[rt<<1|1] <= R-mid) s3 += lsum1[rt<<1|1];
else s3 += R-mid;
}
return Max(s3,Max(s1,s2));
}
int main(){
int op,a,b;
while(scanf("%d",&n)!=EOF){
memset(lsum0,0,sizeof(lsum0));
memset(rsum0,0,sizeof(rsum0));
memset(msum0,0,sizeof(msum0));
memset(lsum1,0,sizeof(lsum1));
memset(rsum1,0,sizeof(rsum1));
memset(msum1,0,sizeof(msum1));
memset(add,0,sizeof(add));
Build(1,1,n);
scanf("%d",&m);
while(m--){
scanf("%d %d %d",&op,&a,&b);
if(op == 1){
Update(1,1,n,a,b);
}
else{
printf("%d\n",Query(1,1,n,a,b));
}
}
}
return 0;
}
HDOJ 3911 Black And White 線段樹 區間合併 成段更新
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.