多写线段树有利于治疗脑洞
0,2操作都好说
操作1需要二分一下能够填脑洞的范围
复杂度m(logn)^2
(rank1怎么跑得辣么快啊,难道有1个Log的做法?)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<cstdlib>
#include<ctime>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
#define mmt(a,v) memset(a,v,sizeof(a))
#define tra(i,u) for(int i=head[u];i;i=e[i].next)
using namespace std;
const int N=200000+5;
struct Node{
int l,r,lx,rx,mx,sum,set;
int len(){return r-l+1;}
void work(){
lx=rx=mx=(set^1)*(r-l+1);
sum=set*(r-l+1);
}
}tr[N<<2];
Node operator + (Node l,Node r){
static Node ans;
ans.l=l.l;ans.r=r.r;
ans.sum=l.sum+r.sum;
if(!l.sum)ans.lx=l.len()+r.lx;
else ans.lx=l.lx;
if(!r.sum)ans.rx=r.len()+l.rx;
else ans.rx=r.rx;
ans.mx=max(l.rx+r.lx,max(l.mx,r.mx));
return ans;
}
#define lc o<<1
#define rc o<<1|1
void pushup(int o){
tr[o].sum=tr[lc].sum+tr[rc].sum;
if(!tr[lc].sum)tr[o].lx=tr[lc].len()+tr[rc].lx;
else tr[o].lx=tr[lc].lx;
if(!tr[rc].sum)tr[o].rx=tr[rc].len()+tr[lc].rx;
else tr[o].rx=tr[rc].rx;
tr[o].mx=max(tr[lc].rx+tr[rc].lx,max(tr[lc].mx,tr[rc].mx));
}
void pushdown(int o){
if(tr[o].set!=-1){
tr[lc].set=tr[rc].set=tr[o].set;
tr[lc].work();tr[rc].work();
tr[o].set=-1;
}
}
int clear(int o,int a,int b){
int l=tr[o].l,r=tr[o].r,ans;
if(l==a&&b==r){
ans=tr[o].sum;
tr[o].set=0;
tr[o].work();
}else{
pushdown(o);
int mid=l+r>>1;
if(b<=mid)ans=clear(lc,a,b);
else if(mid<a)ans=clear(rc,a,b);
else ans=clear(lc,a,mid)+clear(rc,mid+1,b);
pushup(o);
}
return ans;
}
Node query(int o,int a,int b){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return tr[o];
else{
pushdown(o);
int mid=l+r>>1;
if(b<=mid)return query(lc,a,b);
else if(mid<a)return query(rc,a,b);
else return query(lc,a,mid)+query(rc,mid+1,b);
}
}
void update(int o,int a,int b){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)tr[o].set=1,tr[o].work();
else{
pushdown(o);
int mid=l+r>>1;
if(b<=mid)update(lc,a,b);
else if(mid<a)update(rc,a,b);
else update(lc,a,mid),update(rc,mid+1,b);
pushup(o);
}
}
int sum(int o,int a,int b){
int l=tr[o].l,r=tr[o].r;
if(l==a&&b==r)return r-l+1-tr[o].sum;
else{
pushdown(o);
int mid=l+r>>1;
if(b<=mid)return sum(lc,a,b);
else if(mid<a)return sum(rc,a,b);
else return sum(lc,a,mid)+sum(rc,mid+1,b);
}
}
void build(int o,int l,int r){
tr[o].l=l;tr[o].r=r;tr[o].set=-1;tr[o].sum=r-l+1;
if(l==r)return;
int mid=l+r>>1;
build(lc,l,mid);build(rc,mid+1,r);
}
int main(){
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int n,m;scanf("%d%d",&n,&m);
build(1,1,n);
while(m--){
int opt,l,r;
scanf("%d%d%d",&opt,&l,&r);
if(!opt)clear(1,l,r);
else if(opt==2)printf("%d\n",query(1,l,r).mx);
else{
int have=clear(1,l,r);
scanf("%d%d",&l,&r);
if(!have)continue;
int st=l;
while(l<=r){
int mid=l+r>>1;
if(sum(1,st,mid)<=have)l=mid+1;
else r=mid-1;
}
update(1,st,l-1);
}
}
return 0;
}