线段树--luoguP4560 [IOI2014]Wall 砖墙

传送门
很巧啊只需要维护上界和下界就好了
一开始以为要维护四个,其实只用维护两个就好了,如果到了 l = r l=r l=r的时候修改一下序列上的值就行。

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 2000005
#define ls cur<<1
#define rs cur<<1|1
using namespace std;

inline int rd(){
	int x=0,f=1;char c=' ';
	while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x>y?x:y;}

int n,m,mn[N<<2],mx[N<<2],ans[N];

inline void pushdown(int cur,int l,int r){
	if(l==r){
		if(mn[cur]!=-1) ans[l]=min(ans[l],mn[cur]);
		if(mx[cur]!=-1) ans[l]=max(ans[l],mx[cur]);
		return;
	}
	if(mn[cur]!=-1){
		if(mn[ls]!=-1) mn[ls]=min(mn[ls],mn[cur]);
		else mn[ls]=mn[cur];
		mx[ls]=min(mx[ls],mn[cur]);
		if(mn[rs]!=-1) mn[rs]=min(mn[rs],mn[cur]);
		else mn[rs]=mn[cur];
		mx[rs]=min(mx[rs],mn[cur]);
		mn[cur]=-1;
	}
	if(mx[cur]!=-1){
		mx[ls]=max(mx[ls],mx[cur]); mx[rs]=max(mx[rs],mx[cur]);
		if(mn[ls]!=-1) mn[ls]=max(mn[ls],mx[cur]);
		if(mn[rs]!=-1) mn[rs]=max(mn[rs],mx[cur]);
		mx[cur]=-1;
	}
}

void update(int cur,int L,int R,int ql,int qr,int tp,int h){
	if(L<=ql && qr<=R){
		if(tp==1){
			mx[cur]=max(mx[cur],h);
			if(mn[cur]!=-1) mn[cur]=max(mn[cur],h);
		}
		else{
			if(mn[cur]==-1) mn[cur]=h;
			else mn[cur]=min(mn[cur],h);
			if(mx[cur]!=-1) mx[cur]=min(mx[cur],h);
		}
		if(ql==qr){
			if(mn[cur]!=-1) ans[ql]=min(ans[ql],mn[cur]);
			if(mx[cur]!=-1) ans[ql]=max(ans[ql],mx[cur]);
		} return;
	}
	int mid=(ql+qr)>>1; pushdown(cur,ql,qr);
	if(L<=mid) update(ls,L,R,ql,mid,tp,h);
	if(mid<R) update(rs,L,R,mid+1,qr,tp,h);
}

void query(int cur,int ql,int qr){
	pushdown(cur,ql,qr);
	if(ql==qr) {printf("%d\n",ans[ql]);return;}
	int mid=(ql+qr)>>1;
	query(ls,ql,mid); query(rs,mid+1,qr);
}

int main(){
	n=rd(); m=rd(); memset(mn,-1,sizeof mn); memset(mx,-1,sizeof mx);
	int t,l,r,h;
	while(m--){
		t=rd(); l=rd(); r=rd(); h=rd(); ++l,++r;
		update(1,l,r,1,n,t,h);
	}
	query(1,1,n);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值