#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
typedef unsigned long long ui;
inline ll read() {
ll f=1,x=0;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-48;ch=getchar();}
return x*f;
}
struct Line_Tree {
#define maxn 1000005
#define lc 2*t
#define rc 2*t+1
ui n,m,maxt,lazy[4*maxn],a[maxn];
struct Node {
ui lx,rx,mx,num,len;
void init0() { //区间赋0
lx=rx=mx=num=len;
}
void init1() { //区间赋1
lx=rx=mx=num=0;
}
void init() { //初始化
len=0;lx=rx=mx=num=0;
}
}nd[4*maxn],Nd; //nd建树,Nd查询时动态存答案(由于查询到区间满足从左向右)
void pushup(ui t) { //上传
nd[t].mx=max(nd[lc].mx,nd[rc].mx);
nd[t].mx=max(nd[t].mx,nd[lc].rx+nd[rc].lx);
nd[t].num=nd[lc].num+nd[rc].num;
if(nd[lc].num==nd[lc].len) nd[t].lx=nd[lc].len+nd[rc].lx;
else nd[t].lx=nd[lc].lx;
if(nd[rc].num==nd[rc].len) nd[t].rx=nd[lc].rx+nd[rc].len;
else nd[t].rx=nd[rc].rx;
}
void pushdown(ui t) { //下传
if(lazy[t]!=0) { //-1为区间赋0,+1为区间赋1
if(lazy[t]==-1) {
if(nd[lc].len) nd[lc].init0();
if(nd[rc].len) nd[rc].init0();
}
else {
if(nd[lc].len) nd[lc].init1();
if(nd[rc].len) nd[rc].init1();
}
if(nd[lc].len) lazy[lc]=lazy[t];
if(nd[rc].len) lazy[rc]=lazy[t];
lazy[t]=0;
}
}
void Build(ui t,ui l,ui r) { //建树
maxt=max(maxt,t);
if(l==r) {
nd[t].len=1;
nd[t].mx=nd[t].lx=nd[t].rx=nd[t].num=!a[l];
return ;
}
nd[t].len=r-l+1;
ui mid=(l+r)/2;
Build(2*t,l,mid);
Build(2*t+1,mid+1,r);
pushup(t);
}
void Query(ui t,ui l,ui r,ui ll,ui rr) { //查询
if(!nd[t].len) return ;
if(ll<=l&&r<=rr) {
if(Nd.len==0) Nd=nd[t];
else {
Nd.len+=nd[t].len;
Nd.num+=nd[t].num;
Nd.mx=max(Nd.mx,nd[t].mx);
Nd.mx=max(Nd.mx,Nd.rx+nd[t].lx);
if(Nd.len==Nd.num) Nd.lx+=nd[t].lx;
if(nd[t].len==nd[t].num) Nd.rx+=nd[t].len;
else Nd.rx=nd[t].rx;
}
return ;
}
pushdown(t);
ui mid=(l+r)/2;
if(ll<=mid) Query(2*t,l,mid,ll,rr);
if(rr>=mid+1) Query(2*t+1,mid+1,r,ll,rr);
}
void Change(ui t,ui l,ui r,ui ll,ui rr,bool k) { //修改
if(!nd[t].len) return ;
if(ll<=l&&r<=rr) {
if(!k) nd[t].init0(),lazy[t]=-1;
else nd[t].init1(),lazy[t]=1;
return ;
}
pushdown(t);
ui mid=(l+r)/2;
if(ll<=mid) Change(2*t,l,mid,ll,rr,k);
if(rr>=mid+1) Change(2*t+1,mid+1,r,ll,rr,k);
pushup(t);
}
void build() {
Build(1,1,n);
}
ll query(ui ll,ui rr) { //查最长0
Nd.init();
Query(1,1,n,ll,rr);
return Nd.mx;
}
ll query_num(ui ll,ui rr) { //查0的个数
Nd.init();
Query(1,1,n,ll,rr);
return Nd.num;
}
void change(ui ll,ui rr,bool k) { //区间修改 k=0/1 --> 区间赋0/1
Change(1,1,n,ll,rr,k);
}
#undef maxn
}LT;
int main() {
LT.n=read();LT.m=read();
for(ui i=1;i<=LT.n;i++) LT.a[i]=1;
LT.build();
while(LT.m--) {
ui opt=read(),ll=read(),rr=read();
if(!opt) LT.change(ll,rr,0);
else if(opt==1) {
ui ll1=read(),rr1=read(),num=LT.query_num(ll,rr);
LT.change(ll,rr,0);
if(num==rr1-ll1+1) continue;
if(rr-ll+1-num>=LT.query_num(ll1,rr1)) LT.change(ll1,rr1,1);
else {
ui l=ll1,r=rr1,ans=0;
num=rr-ll+1-num;
while(l<=r) {
ui mid=(l+r)/2;
if(LT.query_num(ll1,mid)<=num) ans=mid,l=mid+1;
else r=mid-1;
}
LT.change(ll1,ans,1);
}
}
else cout<<LT.query(ll,rr)<<'\n';
}
return 0;
}
一些变量解释:
lx 区间含左端点最连续0长度
rx 区间含右端点最连续0长度
mx 区间最大连续0长度
num 区间0的个数
len 区间长度
提交记录:Click here.
第12个点数据:Click here.
有没有大佬能帮忙看一下,感激不尽。
P.S.:这道题蒟蒻从去年国庆开始做,当时score∈{5,10},实在调不好就暂时放弃了。最近突然想起该题,调了一天多,进展缓慢,10->30->40->50->80->95,前后大小号交了不下50发,始终欲AC而不能,于是在这里发个帖子,来寻求帮助,望各位大佬理解。
另: @听取MLE声一片 大佬用分块AC了该题,%tql,题解链接