线段树
就是这道题的两种颜色版+普通线段树。
对于每个区间维护一些东西:
sm[0/1]
s
m
[
0
/
1
]
表示这个区间
0/1
0
/
1
的数量,
mx[0/1]
m
x
[
0
/
1
]
表示这个区间连续的
0/1
0
/
1
的最长长度,
lx[0/1]
l
x
[
0
/
1
]
表示以这个区间左端点为起始的连续
0/1
0
/
1
的长度,
rx[0/1]
r
x
[
0
/
1
]
表示以这个区间右端点为结尾的连续
0/1
0
/
1
的长度,
f1
f
1
是重置标记,
f2
f
2
是取反标记。
更新的时候就有t[x].mx[i]=max(t[ls].mx[i],max(t[rs].mx[i],t[ls].rx[i]+t[rs].lx[i]))
注意取反和重置标记的顺序。当重置时要把取反标记清零。当取反时先取反区间,如果有重置标记直接取反重置标记并不打上取反标记。
实现细节见代码:
#include<cctype>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
#define F inline
using namespace std;
struct tree{ int l,r,sm[2],lx[2],rx[2],mx[2],f1,f2; }t[N<<2];
int n,m,a[N];
F char readc(){
static char buf[100000],*l=buf,*r=buf;
if (l==r) r=(l=buf)+fread(buf,1,100000,stdin);
if (l==r) return EOF; return *l++;
}
F int _read(){
int x=0,f=1; char ch=readc();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=readc(); }
while (isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=readc();
return x*f;
}
F void writec(int x){ if (x>9) writec(x/10); putchar(x%10+48); }
F void _write(int x){ writec(x),putchar('\n'); }
#define ls (x<<1)
#define rs (x<<1|1)
F void pshp(int x){
for (int i=0,l=t[x].l,r=t[x].r,mid=l+r>>1;i<2;i++){
t[x].sm[i]=t[ls].sm[i]+t[rs].sm[i];
t[x].mx[i]=max(t[ls].mx[i],max(t[rs].mx[i],t[ls].rx[i]+t[rs].lx[i]));
t[x].lx[i]=t[ls].lx[i]; if (t[x].lx[i]==mid-l+1) t[x].lx[i]+=t[rs].lx[i];
t[x].rx[i]=t[rs].rx[i]; if (t[x].rx[i]==r-mid) t[x].rx[i]+=t[ls].rx[i];
}
}
F void pshd_sm(int x,int w){
int l=t[x].l,r=t[x].r,p=w^1;
t[x].sm[t[x].f1=w]=t[x].mx[w]=t[x].lx[w]=t[x].rx[w]=r-l+1;
t[x].sm[p]=t[x].mx[p]=t[x].f2=t[x].lx[p]=t[x].rx[p]=0;
}
F void pshd_mx(int x){
tree tmp; tmp.l=t[x].l,tmp.r=t[x].r,tmp.f1=-1,tmp.f2=t[x].f2^1;
if (~t[x].f1) tmp.f1=t[x].f1^1,tmp.f2=0;
for (int i=0;i<2;i++){
tmp.rx[i]=t[x].rx[i^1],tmp.lx[i]=t[x].lx[i^1];
tmp.sm[i]=t[x].sm[i^1],tmp.mx[i]=t[x].mx[i^1];
}
t[x]=tmp;
}
F void pshd(int x){
if (~t[x].f1){ int w=t[x].f1; t[x].f1=-1,pshd_sm(ls,w),pshd_sm(rs,w); }
if (t[x].f2){ t[x].f2=0,pshd_mx(ls),pshd_mx(rs); }
}
void build(int x,int l,int r){
t[x].l=l,t[x].r=r,t[x].f1=-1; int mid=l+r>>1,i=a[l];
if (l==r){ t[x].lx[i]=t[x].rx[i]=t[x].mx[i]=t[x].sm[i]=1; return; }
build(ls,l,mid),build(rs,mid+1,r),pshp(x);
}
void mdfy(int x,int l,int r,int w){
int L=t[x].l,R=t[x].r; if (L>r||R<l) return;
if (L>=l&&R<=r){ pshd_sm(x,w); return; }
pshd(x),mdfy(ls,l,r,w),mdfy(rs,l,r,w),pshp(x);
}
void mdfy(int x,int l,int r){
int L=t[x].l,R=t[x].r; if (L>r||R<l) return;
if (L>=l&&R<=r){ pshd_mx(x); return; }
pshd(x),mdfy(ls,l,r),mdfy(rs,l,r),pshp(x);
}
int srch_sm(int x,int l,int r){
int L=t[x].l,R=t[x].r; if (L>r||R<l) return 0;
if (L>=l&&R<=r) return t[x].sm[1]; pshd(x);
return srch_sm(ls,l,r)+srch_sm(rs,l,r);
}
tree srch_mx(int x,int l,int r){
tree tmp; tmp.lx[1]=tmp.rx[1]=tmp.mx[1]=0;
int L=t[x].l,R=t[x].r; if (L>r||R<l) return tmp;
if (L>=l&&R<=r) return t[x]; int mid=L+R>>1;
pshd(x); tree lt=srch_mx(ls,l,r),rt=srch_mx(rs,l,r);
tmp.mx[1]=max(lt.mx[1],max(rt.mx[1],lt.rx[1]+rt.lx[1]));
tmp.lx[1]=lt.lx[1]; if (lt.lx[1]==mid-L+1) tmp.lx[1]+=rt.lx[1];
tmp.rx[1]=rt.rx[1]; if (rt.rx[1]==R-mid) tmp.rx[1]+=lt.rx[1];
return tmp;
}
int main(){
n=_read(),m=_read();
for (int i=1;i<=n;i++) a[i]=_read();
for (build(1,1,n);m;m--){
int f=_read(),l=_read()+1,r=_read()+1;
if (f==0||f==1) { mdfy(1,l,r,f); continue; }
if (f==2) { mdfy(1,l,r); continue; }
if (f==3) { _write(srch_sm(1,l,r)); continue; }
_write(srch_mx(1,l,r).mx[1]);
}
return 0;
}