95pts
查看原帖
95pts
222104
_yjh楼主2022/6/21 20:50
#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,题解链接

2022/6/21 20:50
加载中...