版权声明:转载请附带链接或评论 https://blog.csdn.net/corsica6/article/details/82356742
传送门:bzoj1858
题解
线段树,区间操作
区间赋值操作可以覆盖区间翻转操作。
操作时不断标记下传,
时执行覆盖操作。
代码
#include<bits/stdc++.h>
#define gc getchar()
#define si isdigit(c)
#define RI register
#define lc k<<1
#define rc k<<1|1
#define mid (((l)+(r))>>1)
using namespace std;
const int N=1e5+10;
int n,m,ori[N],op,a,b;
struct node{
int st,zr,rv,cl,cr;
int zmx,zlmx,zrmx;
int omx,olmx,ormx;
node(){st=-1;}
}t[N<<2];
char c;
inline void rd(int &x)
{
c=gc;x=0;
for(;!si;c=gc);
for(;si;c=gc) x=x*10+(c^48);
}
inline void pushup(int k)
{
t[k].zr=t[lc].zr+t[rc].zr;
if(t[lc].zlmx==t[lc].cr-t[lc].cl+1) t[k].zlmx=t[lc].zlmx+t[rc].zlmx;
else t[k].zlmx=t[lc].zlmx;
if(t[rc].zrmx==t[rc].cr-t[rc].cl+1) t[k].zrmx=t[rc].zrmx+t[lc].zrmx;
else t[k].zrmx=t[rc].zrmx;
t[k].zmx=max(max(t[lc].zmx,t[rc].zmx),t[lc].zrmx+t[rc].zlmx);
if(t[lc].olmx==t[lc].cr-t[lc].cl+1) t[k].olmx=t[lc].olmx+t[rc].olmx;
else t[k].olmx=t[lc].olmx;
if(t[rc].ormx==t[rc].cr-t[rc].cl+1) t[k].ormx=t[rc].ormx+t[lc].ormx;
else t[k].ormx=t[rc].ormx;
t[k].omx=max(max(t[lc].omx,t[rc].omx),t[lc].ormx+t[rc].olmx);
}
inline void pushdown(int k)
{
if(t[k].cl==t[k].cr) return;
if(t[k].st!=-1){
int num= (!t[k].zr)?1:0;
t[lc].rv=t[rc].rv=t[k].rv=0;
t[lc].st=t[rc].st=num;t[k].st=-1;
if(num){
t[lc].zr=t[rc].zr=0;
t[lc].zlmx=t[lc].zrmx=t[lc].zmx=0;
t[rc].zlmx=t[rc].zrmx=t[rc].zmx=0;
t[lc].olmx=t[lc].ormx=t[lc].omx=t[lc].cr-t[lc].cl+1;
t[rc].olmx=t[rc].ormx=t[rc].omx=t[rc].cr-t[rc].cl+1;
}else{
t[lc].zr=t[lc].zlmx=t[lc].zrmx=t[lc].zmx=t[lc].cr-t[lc].cl+1;
t[rc].zr=t[rc].zlmx=t[rc].zrmx=t[rc].zmx=t[rc].cr-t[rc].cl+1;
t[lc].olmx=t[lc].ormx=t[lc].omx=0;
t[rc].olmx=t[rc].ormx=t[rc].omx=0;
}
}else if(t[k].rv){
t[lc].rv^=1;t[rc].rv^=1;
t[lc].zr=t[lc].cr-t[lc].cl+1-t[lc].zr;t[rc].zr=t[rc].cr-t[rc].cl+1-t[rc].zr;
t[k].rv=0;
swap(t[lc].zlmx,t[lc].olmx);swap(t[lc].zrmx,t[lc].ormx);swap(t[lc].zmx,t[lc].omx);
swap(t[rc].zlmx,t[rc].olmx);swap(t[rc].zrmx,t[rc].ormx);swap(t[rc].zmx,t[rc].omx);
}
}
inline void build(int k,int l,int r)
{
t[k].cl=l;t[k].cr=r;
if(l==r) {
if(ori[l]){t[k].omx=t[k].olmx=t[k].ormx=1;}
else{t[k].zr=1;t[k].zmx=t[k].zlmx=t[k].zrmx=1;}
return;
}
build(lc,l,mid);build(rc,mid+1,r);
pushup(k);
}
inline void sett(int k,int l,int r,int L,int R,int num)
{
pushdown(k);
if(L<=l && r<=R){
t[k].st=num;
if(num){
t[k].zr=t[k].zmx=t[k].zlmx=t[k].zrmx=0;
t[k].omx=t[k].ormx=t[k].olmx=r-l+1;
}else{
t[k].zr=t[k].zmx=t[k].zlmx=t[k].zrmx=r-l+1;
t[k].omx=t[k].olmx=t[k].ormx=0;
}
return;
}
if(L<=mid) sett(lc,l,mid,L,R,num);
if(R>mid) sett(rc,mid+1,r,L,R,num);
pushup(k);
}
inline void rever(int k,int l,int r,int L,int R)
{
pushdown(k);
if(L<=l && r<=R){
t[k].rv^=1;t[k].zr=(r-l+1-t[k].zr);
swap(t[k].zlmx,t[k].olmx);swap(t[k].zrmx,t[k].ormx);swap(t[k].zmx,t[k].omx);
return;
}
if(L<=mid) rever(lc,l,mid,L,R);
if(R>mid) rever(rc,mid+1,r,L,R);
pushup(k);
}
inline int getsum(int k,int l,int r,int L,int R){
pushdown(k);
if(L<=l && r<=R) return r-l+1-t[k].zr;
int re=0;
if(L<=mid) re=getsum(lc,l,mid,L,R);
if(R>mid) re+=getsum(rc,mid+1,r,L,R);
return re;
}
inline node ask(int k,int l,int r,int L,int R)
{
pushdown(k);
if(L<=l && r<=R) return t[k];
if(R<=mid) return ask(lc,l,mid,L,R);
if(L>mid) return ask(rc,mid+1,r,L,R);
node ql=ask(lc,l,mid,L,R),qr=ask(rc,mid+1,r,L,R),tp;
tp.omx=max(ql.omx,qr.omx);
tp.cl=ql.cl;tp.cr=qr.cr;
if(ql.olmx==ql.cr-ql.cl+1) tp.olmx=ql.olmx+qr.olmx;
else tp.olmx=ql.olmx;
if(qr.ormx==qr.cr-qr.cl+1) tp.ormx=qr.ormx+ql.ormx;
else tp.ormx=qr.ormx;
tp.omx=max(tp.omx,ql.ormx+qr.olmx);
return tp;
}
int main(){
RI int i,j;
rd(n);rd(m);
for(i=1;i<=n;++i) rd(ori[i]);
build(1,1,n);
for(;m;--m){
rd(op);rd(a);rd(b);a++;b++;
if(op<2) sett(1,1,n,a,b,op);
else if(op==2) rever(1,1,n,a,b);
else if(op==3) printf("%d\n",getsum(1,1,n,a,b));
else printf("%d\n",ask(1,1,n,a,b).omx);
}
}