分析
不错,蛮好的一道题
对于操作0,1,我们维护区间覆盖的标记
t
a
g
[
i
]
tag[i]
tag[i]
操作2,我们维护区间取反标记
r
e
v
[
i
]
rev[i]
rev[i]
在区间覆盖的时候,取反标记置为-1
在区间取反的时候,直接修改
r
e
v
rev
rev
操作三就是维护一下区间和即可
s
u
m
[
i
]
sum[i]
sum[i]
操作四维护6个值:
从左数最多有多少个连续的1
从右数最多有多少个连续的1
整个区间最多有多少个连续的1
同理,对于0,我们还有3个值要维护
其实还是蛮好写的
就是数组的实现方式会很复杂且麻烦,至少我还没有转出来
如果有过路大佬会使用数组实现,分享一下呗
最后在gsj大佬和ldx大佬的建议下,我还是改用了结构体来做,确实很方便啊!!
我打算改板子了……嗯,就用结构体吧,思路清晰,代码简短易懂
代码
#include<bits/stdc++.h>
#define in read()
#define N 100009
#define lc (k<<1)
#define rc (k<<1)|1
using namespace std;
inline int read(){
char ch;int f=1,res=0;
while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
while(ch>='0'&&ch<='9'){
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return f==1?res:-res;
}
int n,m,A[N];
struct node{
int sum,l[2],r[2],maxn[2];
int rev,tag,len;
friend inline node operator+(const node &a,const node &b){
node res;
res.tag=-1;res.rev=0;//这个地方一定不能忘了赋值,因为这次是把res返回
res.sum=a.sum+b.sum;res.len=a.len+b.len;
for(int i=0;i<=1;++i){
res.l[i]=(a.l[i]==a.len)?a.l[i]+b.l[i]:a.l[i];
res.r[i]=(b.r[i]==b.len)?b.r[i]+a.r[i]:b.r[i];
res.maxn[i]=max(max(a.maxn[i],b.maxn[i]),a.r[i]+b.l[i]);
}
return res;
}
}seg[N<<2];
inline void C(int k,int l,int r,int v){
seg[k].rev=0;seg[k].tag=v;
seg[k].sum=(r-l+1)*v;
seg[k].l[1]=seg[k].r[1]=seg[k].maxn[1]=v*(r-l+1);
seg[k].l[0]=seg[k].r[0]=seg[k].maxn[0]=(v^1)*(r-l+1);
}
inline void R(int k,int l,int r){
seg[k].rev^=1;seg[k].sum=(r-l+1)-seg[k].sum;
swap(seg[k].l[1],seg[k].l[0]);swap(seg[k].r[1],seg[k].r[0]);
swap(seg[k].maxn[0],seg[k].maxn[1]);
}
inline void pushdown(int k,int l,int r){
int mid=l+r>>1;
if(seg[k].tag!=-1) C(lc,l,mid,seg[k].tag),C(rc,mid+1,r,seg[k].tag),seg[k].tag=-1;
if(seg[k].rev) R(lc,l,mid),R(rc,mid+1,r),seg[k].rev=0;
}
inline void build(int k,int l,int r){
seg[k].tag=-1;seg[k].rev=0;
if(l==r){
seg[k].sum=A[l];seg[k].len=1;
seg[k].l[1]=seg[k].r[1]=seg[k].maxn[1]=A[l]*(r-l+1);
seg[k].l[0]=seg[k].r[0]=seg[k].maxn[0]=(A[l]^1)*(r-l+1);
return;
}
int mid=l+r>>1;
build(lc,l,mid);build(rc,mid+1,r);
seg[k]=seg[lc]+seg[rc];
}
inline void cover(int k,int l,int r,int x,int y,int v){
if(x<=l&&r<=y){ C(k,l,r,v); return;}
pushdown(k,l,r);
int mid=l+r>>1;
if(x<=mid) cover(lc,l,mid,x,y,v);
if(y>mid) cover(rc,mid+1,r,x,y,v);
seg[k]=seg[lc]+seg[rc];
}
inline void reverse(int k,int l,int r,int x,int y){
if(x<=l&&r<=y){R(k,l,r);return;}
pushdown(k,l,r);
int mid=l+r>>1;
if(x<=mid) reverse(lc,l,mid,x,y);
if(y>mid) reverse(rc,mid+1,r,x,y);
seg[k]=seg[lc]+seg[rc];
}
inline node query(int k,int l,int r,int x,int y){
if(x<=l&&r<=y){return seg[k];}
pushdown(k,l,r);
int mid=l+r>>1;
if(y<=mid) return query(lc,l,mid,x,y);
if(x>mid) return query(rc,mid+1,r,x,y);
return query(lc,l,mid,x,y)+query(rc,mid+1,r,x,y);
}
int main(){
n=in;m=in;
int i,j,k;
for(i=1;i<=n;++i) A[i]=in;
build(1,1,n);
int op,a,b;
for(i=1;i<=m;++i){
op=in;a=in;b=in;a++;b++;
if(op==0) { cover(1,1,n,a,b,0); }
if(op==1) { cover(1,1,n,a,b,1); }
if(op==2) { reverse(1,1,n,a,b); }//
if(op==3) { printf("%d\n",query(1,1,n,a,b).sum);}
if(op==4) { printf("%d\n",query(1,1,n,a,b).maxn[1]);}
}
return 0;
}