Time Limit: 2000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
N个数排成一列,每个数的大小为1或者0。有两种操作,第一种操作是把一段区间内的每个数异或1,第二种操作是询问区间内最长连续1的长度。
第一行一个整数N(1≤N≤100000),表示N个数。第二行N个数。接下来一行一个整数M(1≤M≤100000),表示M个操作,接下来M行每行三个整数K,L,R。K=1表示把L到R这段区间的数全部异或上1,K=0表示询问L到R这段区间内最长连续1的长度。
对于每个询问,输出对应的答案,每个询问占一行。
5
0 1 0 0 1
5
0 1 4
1 1 1
0 1 4
1 3 4
0 1 4
1
2
4
#include
using namespace std;
const int maxn = 1e5+100;
struct node
{
int lsum1,rsum1,lsum2,rsum2,l,r,sum1,sum2,lazy,len;//sum1代表1的情况,sum2代表0的情况
} tree[maxn<<2];
int n,m;
//lazy标记下移,0-1反转
void pushdown(int root)
{
if(!tree[root].lazy)
return;
tree[root<<1].lazy ^= 1;
tree[root<<1|1].lazy ^= 1;
swap(tree[root<<1].sum1,tree[root<<1].sum2);
swap(tree[root<<1].lsum1,tree[root<<1].lsum2);
swap(tree[root<<1].rsum1,tree[root<<1].rsum2);
swap(tree[root<<1|1].sum1,tree[root<<1|1].sum2);
swap(tree[root<<1|1].lsum1,tree[root<<1|1].lsum2);
swap(tree[root<<1|1].rsum1,tree[root<<1|1].rsum2);
tree[root].lazy = 0;//当前的lazy标记需要取消
}
//向上更新
void pushup(int root)
{
tree[root].lsum1=tree[root<<1].lsum1;
tree[root].lsum2=tree[root<<1].lsum2;
if(tree[root<<1].lsum1==tree[root<<1].len) tree[root].lsum1+=tree[root<<1|1].lsum1;//当最左边连续1的个数等于长度的时候
if(tree[root<<1].lsum2==tree[root<<1].len) tree[root].lsum2+=tree[root<<1|1].lsum2;
tree[root].rsum1=tree[root<<1|1].rsum1;
tree[root].rsum2=tree[root<<1|1].rsum2;
if(tree[root<<1|1].rsum1==tree[root<<1|1].len) tree[root].rsum1+=tree[root<<1].rsum1;
if(tree[root<<1|1].rsum2==tree[root<<1|1].len) tree[root].rsum2+=tree[root<<1].rsum2;
tree[root].sum1 = max(max(tree[root<<1].sum1, tree[root<<1|1].sum1), tree[root<<1].rsum1+tree[root<<1|1].lsum1);
tree[root].sum2 = max(max(tree[root<<1].sum2, tree[root<<1|1].sum2), tree[root<<1].rsum2+tree[root<<1|1].lsum2);
}
void build_tree(int l,int r,int root)
{
tree[root].l = l,tree[root].r = r,tree[root].lazy = 0;
tree[root].len = r - l + 1;
if(l == r)
{
int x;
scanf("%d",&x);
if(x)
{
tree[root].lsum1 = tree[root].rsum1 = tree[root].sum1 = 1;
tree[root].lsum2 = tree[root].rsum2 = tree[root].sum2 = 0;
}
else
{
tree[root].lsum1 = tree[root].rsum1 = tree[root].sum1 = 0;
tree[root].lsum2 = tree[root].rsum2 = tree[root].sum2 = 1;
}
return ;
}
int mid = (l + r) >> 1;
build_tree(l,mid,root<<1);
build_tree(mid+1,r,root<<1|1);
pushup(root);//记得向上更新
}
void change(int a,int b,int l,int r,int root)
{
if(a <= l && b >= r)
{
swap(tree[root].sum1,tree[root].sum2);
swap(tree[root].lsum1,tree[root].lsum2);
swap(tree[root].rsum1,tree[root].rsum2);
tree[root].lazy ^= 1;//lazy标记
return ;
}
int mid = (l + r) / 2;
pushdown(root);//标记下移
if(b <= mid)
change(a,b,l,mid,root<<1);
else if(a > mid)
change(a,b,mid+1,r,root<<1|1);
else
{
change(a,mid,l,mid,root<<1);
change(mid+1,b,mid+1,r,root<<1|1);
}
pushup(root);
}
int query(int a,int b,int l,int r,int root)
{
if(a <= l && b >= r)
return tree[root].sum1;
int mid = (l + r)/2;
pushdown(root);
if(b <= mid)
return query(a,b,l,mid,root<<1);
else if(a > mid)
return query(a,b,mid+1,r,root<<1|1);
else
{
//看起来很多 就是左子树的最大值和右子树的最大值和两个子树合并起来的值取最大的一个
int m1 = query(a,mid,l,mid,root<<1);
int m2 = query(mid+1,b,mid+1,r,root<<1|1);
int m3 = max(m1,m2);
int m4 = min(tree[root<<1].rsum1,mid-a+1);
int m5 = min(b-mid,tree[root<<1|1].lsum1);
return max(m3,m4+m5);
}
pushup(root);
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
build_tree(1,n,1);
scanf("%d",&m);
while(m--)
{
int k,a,b;
scanf("%d%d%d",&k,&a,&b);
if(k)
change(a,b,1,n,1);
else
{
int ans = query(a,b,1,n,1);
printf("%d\n",ans);
}
}
}
return 0;
}