题目描述
lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:
0 a b 把[a, b]区间内的所有数全变成0
1 a b 把[a, b]区间内的所有数全变成1
2 a b 把[a,b]区间内的所有数全部取反,也就是说把所有的0变成1,把所有的1变成0
3 a b 询问[a, b]区间内总共有多少个1
4 a b 询问[a, b]区间内最多有多少个连续的1
对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?
数据范围
1<=n, m<=100000
样例输入
10 10
0 0 0 1 1 0 1 0 1 1
1 0 2
3 0 5
2 2 2
4 0 4
0 3 6
2 3 7
4 2 8
1 0 5
0 5 6
3 3 9
样例输出
5
2
6
5
解题思路
维护一些属性与标记(什么属性什么标记就略了A.A)
注意rev应该是rev[x]^=1,而不是rev[x]=1
还有如果将一段区间改为了0或1,应该删掉rev标记
害我调了一中午QWQ
代码
#include <bits/stdc++.h>
using namespace std;
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
struct node{
int L,r,Sum[2],MaxL[2],Maxr[2],Max[2],c1,c0,rev;
}Tree[400005];
int vl[100005];
int GetSize(int v){
return Tree[v].r-Tree[v].L+1;
}
void PushUp(int v,int op){
Tree[v].Sum[op]=Tree[2*v].Sum[op]+Tree[2*v+1].Sum[op];
Tree[v].MaxL[op]=Tree[2*v].MaxL[op]+(Tree[2*v].MaxL[op]==GetSize(2*v)?Tree[2*v+1].MaxL[op]:0);
Tree[v].Maxr[op]=Tree[2*v+1].Maxr[op]+(Tree[2*v+1].Maxr[op]==GetSize(2*v+1)?Tree[2*v].Maxr[op]:0);
Tree[v].Max[op]=max(Tree[2*v].Max[op],Tree[2*v+1].Max[op]);
Tree[v].Max[op]=max(Tree[v].MaxL[op],Tree[v].Max[op]);
Tree[v].Max[op]=max(Tree[v].Maxr[op],Tree[v].Max[op]);
Tree[v].Max[op]=max(Tree[2*v].Maxr[op]+Tree[2*v+1].MaxL[op],Tree[v].Max[op]);
}
int PushUp(int v){PushUp(v,0);PushUp(v,1);return 0;}
void PushDown(int v){
if(Tree[v].c1){
Tree[2*v].c0=0;
Tree[2*v].c1=1;
Tree[2*v].rev=0;
Tree[2*v].Max[0]=Tree[2*v].Sum[0]=Tree[2*v].MaxL[0]=Tree[2*v].Maxr[0]=0;
Tree[2*v].Max[1]=Tree[2*v].Sum[1]=Tree[2*v].MaxL[1]=Tree[2*v].Maxr[1]=GetSize(2*v);
Tree[2*v+1].c0=0;
Tree[2*v+1].c1=1;
Tree[2*v+1].rev=0;
Tree[2*v+1].Max[0]=Tree[2*v+1].Sum[0]=Tree[2*v+1].MaxL[0]=Tree[2*v+1].Maxr[0]=0;
Tree[2*v+1].Max[1]=Tree[2*v+1].Sum[1]=Tree[2*v+1].MaxL[1]=Tree[2*v+1].Maxr[1]=GetSize(2*v+1);
Tree[v].c1=0;
}
if(Tree[v].c0){
Tree[2*v].c1=0;
Tree[2*v].c0=1;
Tree[2*v].rev=0;
Tree[2*v].Max[1]=Tree[2*v].Sum[1]=Tree[2*v].MaxL[1]=Tree[2*v].Maxr[1]=0;
Tree[2*v].Max[0]=Tree[2*v].Sum[0]=Tree[2*v].MaxL[0]=Tree[2*v].Maxr[0]=GetSize(2*v);
Tree[2*v+1].c1=0;
Tree[2*v+1].c0=1;
Tree[2*v+1].rev=0;
Tree[2*v+1].Max[1]=Tree[2*v+1].Sum[1]=Tree[2*v+1].MaxL[1]=Tree[2*v+1].Maxr[1]=0;
Tree[2*v+1].Max[0]=Tree[2*v+1].Sum[0]=Tree[2*v+1].MaxL[0]=Tree[2*v+1].Maxr[0]=GetSize(2*v+1);
Tree[v].c0=0;
}
if(Tree[v].rev){
Tree[2*v].rev^=1;
Tree[2*v+1].rev^=1;
swap(Tree[2*v].Max[0],Tree[2*v].Max[1]);
swap(Tree[2*v].Sum[0],Tree[2*v].Sum[1]);
swap(Tree[2*v].MaxL[0],Tree[2*v].MaxL[1]);
swap(Tree[2*v].Maxr[0],Tree[2*v].Maxr[1]);
swap(Tree[2*v+1].Sum[0],Tree[2*v+1].Sum[1]);
swap(Tree[2*v+1].Max[0],Tree[2*v+1].Max[1]);
swap(Tree[2*v+1].MaxL[0],Tree[2*v+1].MaxL[1]);
swap(Tree[2*v+1].Maxr[0],Tree[2*v+1].Maxr[1]);
Tree[v].rev=0;
}
}
void Build(int v,int L,int r){
Tree[v]=(node){L,r,0,0,0,0,0,0,0,0,0,0,0};
if(L==r)return;
Build(2*v,L,(L+r)/2);
Build(2*v+1,(L+r)/2+1,r);
}
void Make_Same(int v,int L,int r,int op){
if(r<Tree[v].L||Tree[v].r<L)return;
if(L<=Tree[v].L&&Tree[v].r<=r){
if(op==0)Tree[v].c0=1,Tree[v].c1=0,Tree[v].rev=0;
if(op==1)Tree[v].c0=0,Tree[v].c1=1,Tree[v].rev=0;
Tree[v].Max[!op]=Tree[v].Sum[!op]=Tree[v].MaxL[!op]=Tree[v].Maxr[!op]=0;
Tree[v].Max[op]=Tree[v].Sum[op]=Tree[v].MaxL[op]=Tree[v].Maxr[op]=GetSize(v);
return;
}
PushDown(v);
Make_Same(2*v,L,r,op);
Make_Same(2*v+1,L,r,op);
PushUp(v);
}
void Rev(int v,int L,int r){
if(r<Tree[v].L||Tree[v].r<L)return;
if(L<=Tree[v].L&&Tree[v].r<=r){
Tree[v].rev^=1;
swap(Tree[v].Max[0],Tree[v].Max[1]);
swap(Tree[v].Sum[0],Tree[v].Sum[1]);
swap(Tree[v].MaxL[0],Tree[v].MaxL[1]);
swap(Tree[v].Maxr[0],Tree[v].Maxr[1]);
return;
}
PushDown(v);
Rev(2*v,L,r);
Rev(2*v+1,L,r);
PushUp(v);
}
int AskTot(int v,int L,int r){
if(r<Tree[v].L||Tree[v].r<L)return 0;
if(L<=Tree[v].L&&Tree[v].r<=r)
return Tree[v].Sum[1];
PushDown(v);
return AskTot(2*v,L,r)+AskTot(2*v+1,L,r);
}
int Ask(int v,int L,int r){
if(r<Tree[v].L||Tree[v].r<L)return 0;
if(L<=Tree[v].L&&Tree[v].r<=r)
return Tree[v].Max[1];
PushDown(v);
int t=max(Ask(2*v,L,r),Ask(2*v+1,L,r));
t=max(t,min(Tree[2*v+1].L+Tree[2*v+1].MaxL[1]-1,r)-max(Tree[2*v].r-Tree[2*v].Maxr[1]+1,L)+1);
return t;
}
int main(){
int n=Getint(),m=Getint();
for(int i=1;i<=n;i++)vl[i]=Getint();
Build(1,1,n);
for(int i=1;i<=n;i++)Make_Same(1,i,i,vl[i]);
while(m--){
int op=Getint(),L=Getint()+1,r=Getint()+1;
if(op==0||op==1)Make_Same(1,L,r,op);
if(op==2)Rev(1,L,r);
if(op==3)cout<<AskTot(1,L,r)<<"\n";
if(op==4)cout<<Ask(1,L,r)<<"\n";
}
return 0;
}