社区讨论

线段树水题100pts,萌新求助!

P4344[SHOI2015] 脑洞治疗仪参与者 2已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@lo28m1iw
此快照首次捕获于
2023/10/23 09:46
2 年前
此快照最后确认于
2023/11/03 10:00
2 年前
查看原帖
RT,被最后的subtask卡了,虽然100但是没有A。看了讨论区,好像说是区间冲突,但是我想了几遍,觉得我的实现应该不会冲突。所以特来求助谷内大佬hack!
悬赏一个关注。
源代码:
CPP
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5e5+10;
int n,m;
struct node {
	int l,r,sum,lmax,rmax,maxn,la;
	//la: 1 - all 0;0 - all 1;2 - not all
}tr[N<<2];
inline void pushup(int x){
	tr[x].lmax=tr[x<<1].lmax;
	if(tr[x<<1].sum==tr[x<<1].r-tr[x<<1].l+1){
		tr[x].lmax+=tr[x<<1|1].lmax;
	}
	tr[x].rmax=tr[x<<1|1].rmax;
	if(tr[x<<1|1].sum==tr[x<<1|1].r-tr[x<<1|1].l+1){
		tr[x].rmax+=tr[x<<1].rmax;
	}
	tr[x].maxn=max({tr[x].lmax,tr[x].rmax,tr[x<<1].rmax+tr[x<<1|1].lmax,tr[x<<1].maxn,tr[x<<1|1].maxn});
	tr[x].sum=tr[x<<1].sum+tr[x<<1|1].sum;
}
inline void pushdown(int x){
	tr[x<<1].sum=tr[x<<1].lmax=tr[x<<1].rmax=tr[x<<1].maxn=tr[x].la*(tr[x<<1].r-tr[x<<1].l+1);
	tr[x<<1|1].sum=tr[x<<1|1].lmax=tr[x<<1|1].rmax=tr[x<<1|1].maxn=tr[x].la*(tr[x<<1|1].r-tr[x<<1|1].l+1);
	tr[x<<1].la=tr[x<<1|1].la=tr[x].la;
	tr[x].la=2;
}
inline void build(int x,int l,int r){
	tr[x].l=l,tr[x].r=r;
	tr[x].la=2;
	tr[x].maxn=tr[x].lmax=tr[x].rmax=tr[x].sum=0;
	if(l==r){
		return;
	}
	int mid=(l+r)>>1;
	build(x<<1,l,mid);
	build(x<<1|1,mid+1,r);
}
inline void dig(int x,int l,int r){
	if(l<=tr[x].l&&tr[x].r<=r){
		tr[x].sum=tr[x].lmax=tr[x].rmax=tr[x].maxn=tr[x].r-tr[x].l+1;
		tr[x].la=1;
		return;
	}
	if(tr[x].la!=2){
		pushdown(x);
	}
	int mid=(tr[x].l+tr[x].r)>>1;
	if(l<=mid){
		dig(x<<1,l,r);
	}
	if(r>mid){
		dig(x<<1|1,l,r);
	}
	pushup(x);
}
inline void fill(int x,int l,int r){
	if(l<=tr[x].l&&tr[x].r<=r){
		tr[x].sum=tr[x].lmax=tr[x].rmax=tr[x].maxn=0;
		tr[x].la=0;
		return;
	}
	if(tr[x].la!=2){
		pushdown(x);
	}
	int mid=(tr[x].l+tr[x].r)>>1;
	if(l<=mid){
		fill(x<<1,l,r);
	}
	if(r>mid){
		fill(x<<1|1,l,r);
	}
	pushup(x);
}
inline node hb(node x,node y){
	node z;
	z.lmax=x.lmax;
	if(x.sum==x.r-x.l+1){
		z.lmax+=y.lmax;
	}
	z.rmax=y.rmax;
	if(y.sum==y.r-y.l+1){
		z.rmax+=x.rmax;
	}
	z.maxn=max({z.lmax,z.rmax,x.rmax+y.lmax,x.maxn,y.maxn});
	z.sum=x.sum+y.sum;
	return z;
}
inline node query(int x,int l,int r){
	if(l<=tr[x].l&&tr[x].r<=r){
		return tr[x];
	}
	if(tr[x].la!=2){
		pushdown(x);
	}
	int mid=(tr[x].l+tr[x].r)>>1;
	if(r<=mid){
		return query(x<<1,l,r);
	}
	else if(l>mid){
		return query(x<<1|1,l,r);
	}
	else{
		return hb(query(x<<1,l,r),query(x<<1|1,l,r));
	}
}
inline void treat(int x,int l,int r,int k){
	int ans=r,he=l,ta=r;
	while(he<=ta){
		int mid=(he+ta)>>1;
		if(query(1,l,mid).sum>=k){
			ta=mid-1;
			ans=mid;
		}
		else{
			he=mid+1;
		}
	}
	fill(1,l,ans);
}
int main(){
	scanf("%d%d",&n,&m);
	int op,l,r,u,v;
	build(1,1,n);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&op,&l,&r);
		if(op==0){
			dig(1,l,r);
		}
		else if(op==1){
			scanf("%d%d",&u,&v);
			int num=r-l+1-query(1,l,r).sum;
			if(num==0){
				continue;
			}
			dig(1,l,r);
			treat(1,u,v,num);
		}
		else{
			node ans=query(1,l,r);
			printf("%d\n",ans.maxn);
		}
	}
}

回复

1 条回复,欢迎继续交流。

正在加载回复...