这个题有毒 我调了3个小时 各种奇葩错 (还是我太菜了)
这题就线段树维护一个区间1的个数 0的个数 左端最长连续0 右端最长连续0 区间内最长连续0 转移的思路还是很好想的 对于那个补脑洞的操作(明明脑洞越来越多) 二分一下 再区间修改
还是得多码
(我学了假的线段树 常数大到离谱)
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m;
struct node{
bool flag,addflag;
int sum[2],mx,lx,rx,l,r;
bool operator == (const node&ph) const{
return l==ph.l&&r==ph.r;
}
}t[N*4],null;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void pushdown(int pos,int l,int r){
int mid=(l+r)>>1;
t[pos<<1].flag=t[pos<<1|1].flag=t[pos].flag;
t[pos<<1].addflag=t[pos<<1|1].addflag=1;
t[pos<<1].sum[0]=mid-l+1,t[pos<<1|1].sum[0]=r-mid,t[pos<<1|1].sum[1]=t[pos<<1].sum[1]=0;
if(t[pos].flag) swap(t[pos<<1|1].sum[0],t[pos<<1|1].sum[1]),swap(t[pos<<1].sum[0],t[pos<<1].sum[1]);
t[pos<<1].mx=t[pos<<1].lx=t[pos<<1].rx=t[pos].flag?0:mid-l+1;
t[pos<<1|1].mx=t[pos<<1|1].lx=t[pos<<1|1].rx=t[pos].flag?0:r-mid;
t[pos].addflag=0;
}
void update(int pos,int l,int r){
int mid=(l+r)>>1;
t[pos].sum[0]=t[pos<<1].sum[0]+t[pos<<1|1].sum[0];
t[pos].sum[1]=t[pos<<1].sum[1]+t[pos<<1|1].sum[1];
t[pos].mx=max(max(max(t[pos<<1].lx,t[pos<<1|1].rx),max(t[pos<<1].mx,t[pos<<1|1].mx)),t[pos<<1].rx+t[pos<<1|1].lx);
t[pos].lx=t[pos<<1].lx==mid-l+1?t[pos<<1].lx+t[pos<<1|1].lx:t[pos<<1].lx;
t[pos].rx=t[pos<<1|1].rx==r-mid?t[pos<<1].rx+t[pos<<1|1].rx:t[pos<<1|1].rx;
}
void build(int pos,int l,int r){
t[pos].l=l,t[pos].r=r,t[pos].sum[1]=r-l+1;
if(l==r) return;
int mid=(l+r)>>1;
build(pos<<1,l,mid),build(pos<<1|1,mid+1,r);
}
void add(int pos,int l,int r,int nl,int nr,int v){
if(l>nr||r<nl) return;
if(l>=nl&&r<=nr){
t[pos].addflag=1;
t[pos].flag=v;
t[pos].sum[0]=t[pos].mx=t[pos].lx=t[pos].rx=v?0:r-l+1;
t[pos].sum[1]=v?r-l+1:0;
return;
}
if(t[pos].addflag)pushdown(pos,l,r);
int mid=(l+r)>>1;
add(pos<<1,l,mid,nl,nr,v);add(pos<<1|1,mid+1,r,nl,nr,v);
update(pos,l,r);
}
int asksum(int pos,int l,int r,int nl,int nr,int v){
if(l>nr||r<nl) return 0;
if(l>=nl&&r<=nr) {
return t[pos].sum[v];
}
if(t[pos].addflag)pushdown(pos,l,r);
int mid=(l+r)>>1;
return asksum(pos<<1,l,mid,nl,nr,v)+asksum(pos<<1|1,mid+1,r,nl,nr,v);
}
node work(node x,node y){
node p;
if(x==null||y==null) return p=x==null?y:x;
p.mx=max(max(max(x.lx,y.rx),max(x.mx,y.mx)),x.rx+y.lx);
p.lx=x.lx==x.r-x.l+1?x.lx+y.lx:x.lx;
p.rx=y.rx==y.r-y.l+1?x.rx+y.rx:y.rx;
p.l=x.l,p.r=y.r;
return p;
}
node askmax(int pos,int l,int r,int nl,int nr){
if(l>nr||r<nl) return null;
if(l>=nl&&r<=nr) return t[pos];
if(t[pos].addflag)pushdown(pos,l,r);
int mid=(l+r)>>1;
node p=work(askmax(pos<<1,l,mid,nl,nr),askmax(pos<<1|1,mid+1,r,nl,nr));
return p;
}
int main(){
n=read(),m=read();
build(1,1,n);
for(int i=1,op,x,y;i<=m;i++){
op=read();
if(op==0){
int x=read(),y=read();
add(1,1,n,x,y,0);
}
else if(op==1){
int l0=read(),r0=read(),l1=read(),r1=read();
int s1=asksum(1,1,n,l0,r0,1);
if(s1){
add(1,1,n,l0,r0,0);
if(asksum(1,1,n,l1,r1,0)<=s1) add(1,1,n,l1,r1,1);
else{
int l=l1,r=r1;
while(l<r){
int mid=(l+r)>>1;
if(asksum(1,1,n,l1,mid,0)<s1) l=mid+1;
else r=mid;
}
add(1,1,n,l1,r,1);
}
}
}
else{
int x=read(),y=read();
node p=askmax(1,1,n,x,y);
printf("%d\n",max(max(p.lx,p.rx),p.mx));
}
}
}