BZOJ4364:[IOI2014]Wall

浅谈区间最值操作与历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html

题目传送门:https://lydsy.com/JudgeOnline/problem.php?id=4364

似乎可以不用吉司机线段树的作法……因为只需要维护区间最大最小值,也只有区间取最大最小值操作,所以可以直接用普通的线段树延迟标记解决这道问题。只要把最大值标记和最小值标记之间的关系处理得当即可。

时间复杂度:\(O((n+m)logn)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;

const int maxn=2e6+6,inf=1e9;

int n,m;

int read() {
	int x=0,f=1;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
	return x*f;
}

struct segmemt_tree {
	int mx[maxn<<2],mn[maxn<<2];
	int tagmx[maxn<<2],tagmn[maxn<<2];

	void update(int p) {
		mx[p]=max(mx[p<<1],mx[p<<1|1]);
		mn[p]=min(mn[p<<1],mn[p<<1|1]);
	}

	void build(int p,int l,int r) {
		tagmx[p]=-inf,tagmn[p]=inf;
		if(l==r)return;
		int mid=(l+r)>>1;
		build(p<<1,l,mid);
		build(p<<1|1,mid+1,r);
	}

	void Max_tag(int p,int v) {
		mx[p]=max(mx[p],v),mn[p]=max(mn[p],v);
		tagmx[p]=max(tagmx[p],v);tagmn[p]=max(tagmn[p],v);
	}

	void Min_tag(int p,int v) {
		mx[p]=min(mx[p],v),mn[p]=min(mn[p],v);
		tagmx[p]=min(tagmx[p],v),tagmn[p]=min(tagmn[p],v);
	}

	void push_down(int p) {
		if(tagmx[p]!=-inf) {
			Max_tag(p<<1,tagmx[p]);
			Max_tag(p<<1|1,tagmx[p]);
			tagmx[p]=-inf;
		}
		if(tagmn[p]!=inf) {
			Min_tag(p<<1,tagmn[p]);
			Min_tag(p<<1|1,tagmn[p]);
			tagmn[p]=inf;
		}
	}

	void Max(int p,int l,int r,int L,int R,int v) {
		if(L<=l&&r<=R) {
			Max_tag(p,v);
			return;
		}
		int mid=(l+r)>>1;push_down(p);
		if(L<=mid)Max(p<<1,l,mid,L,R,v);
		if(R>mid)Max(p<<1|1,mid+1,r,L,R,v);
		update(p);
	}

	void Min(int p,int l,int r,int L,int R,int v) {
		if(L<=l&&r<=R) {
			Min_tag(p,v);
			return;
		}
		int mid=(l+r)>>1;push_down(p);
		if(L<=mid)Min(p<<1,l,mid,L,R,v);
		if(R>mid)Min(p<<1|1,mid+1,r,L,R,v);
		update(p);
	}

	void print(int p,int l,int r) {
		if(l==r) {printf("%d\n",mx[p]);return;}
		int mid=(l+r)>>1;push_down(p);
		print(p<<1,l,mid),print(p<<1|1,mid+1,r);
	}
}T;

int main() {
	n=read(),m=read();T.build(1,1,n);
	for(int i=1;i<=m;i++) {
		int opt=read(),l=read()+1,r=read()+1,v=read();
		if(opt==1)T.Max(1,1,n,l,r,v);
		else T.Min(1,1,n,l,r,v);
	}T.print(1,1,n);
	return 0;
}
posted @ 2019-01-06 09:45  AKMer  阅读(168)  评论(0编辑  收藏  举报