//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; }