题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3911
题意:
给你一段01序列,有两个操作:
1.区间异或,2.询问区间最长的连续的1得长度
思路:
线段树区间合并,开六个数组分别表示:
lsum0 区间左边界开始从左到右连续0的个数
rsum0 区间右边界开始从右到左连续0的个数
lsum1 rsum1 根据上面的可以看出
sum0 区间最长的连续0的个数
sum1 区间最长的连续1的个数
碰到i区间异或操作,我们直接奖这几个数组换下就好了
实现代码:
#include<bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ll long long
#define ull unsigned long long const int M = 1e5 + ;
int lsum1[M<<],rsum1[M<<],sum1[M<<],lsum0[M<<],rsum0[M<<],sum0[M<<],lazy[M<<];
int a[M];
void pushup(int l,int r,int rt){
mid;
lsum1[rt] = lsum1[rt<<]; lsum0[rt] = lsum0[rt<<];
rsum1[rt] = rsum1[rt<<|]; rsum0[rt] = rsum0[rt<<|];
if(lsum1[rt] == m-l+) lsum1[rt] += lsum1[rt<<|];
if(rsum1[rt] == r-m) rsum1[rt] += rsum1[rt<<];
if(lsum0[rt] == m-l+) lsum0[rt] += lsum0[rt<<|];
if(rsum0[rt] == r-m) rsum0[rt] += rsum0[rt<<];
sum0[rt] = max(max(sum0[rt<<],sum0[rt<<|]),rsum0[rt<<]+lsum0[rt<<|]);
sum1[rt] = max(max(sum1[rt<<],sum1[rt<<|]),rsum1[rt<<]+lsum1[rt<<|]);
} void swa(int rt){
swap(lsum0[rt],lsum1[rt]);
swap(rsum0[rt],rsum1[rt]);
swap(sum0[rt],sum1[rt]);
} void pushdown(int l,int r,int rt){
if(lazy[rt]){
lazy[rt<<] ^= lazy[rt];
lazy[rt<<|] ^= lazy[rt];
swa(rt<<); swa(rt<<|);
lazy[rt] = ;
}
} void build(int l,int r,int rt){
lazy[rt] = ;
lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
if(l == r){
if(a[l]){
lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else{
lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
return ;
}
mid;
build(lson); build(rson);
pushup(l,r,rt);
} void update(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
lazy[rt] ^= ;
swa(rt);
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) update(L,R,lson);
if(R > m) update(L,R,rson);
pushup(l,r,rt);
} int query(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum1[rt];
}
pushdown(l,r,rt);
mid;
if(L > m) return query(L,R,rson);
if(R <= m) return query(L,R,lson);
int t1 = query(L,R,lson);
int t2 = query(L,R,rson);
int rs = min(lsum1[rt<<|],R-m);
int ls = min(m-L+,rsum1[rt<<]);
return max(max(t1,t2),ls+rs);
} int main()
{
int n,op,x,y,q;
while(scanf("%d",&n)!=EOF){
for(int i = ;i <= n;i ++){
scanf("%d",&a[i]);
}
build(,n,);
scanf("%d",&q);
while(q--){
scanf("%d%d%d",&op,&x,&y);
if(op == ) update(x,y,,n,);
else printf("%d\n",query(x,y,,n,));
}
}
return ;
}