【luoguP1382】楼房

题目描述

离散化,线段树维护区间修改,发现询问都是单点的\(max\),不妨把标记留在点上,不用下传,查询时取个\(max\)就可以了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define lc (p<<1)
#define rc (p<<1|1)
using namespace std;

const int MAXN=400010;
const int MAXM=1600010;

inline int read(){
	int x=0,f=1; char c=getchar();
	while(c<'0'){ if(c=='-') f=-1; c=getchar(); }
	while(c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}

int n,x[MAXN],cnt,num;

struct Data{
	int l,r,h;
} a[MAXN];

map<int,int> Map;

int tree[MAXM],rev[MAXN];

inline void update(int L,int R,int h,int p=1,int l=1,int r=num){
	if(L<=l&&r<=R){
		tree[p]=max(tree[p],h);
		return;
	}
	int mid=(l+r)>>1;
	if(L<=mid) update(L,R,h,lc,l,mid);
	if(R>mid) update(L,R,h,rc,mid+1,r);
}

inline int query(int x,int p=1,int l=1,int r=num){
	if(l==r) return tree[p];
	int mid=(l+r)>>1,ans=tree[p];
	if(x<=mid) ans=max(ans,query(x,lc,l,mid));
	else ans=max(ans,query(x,rc,mid+1,r));
	return ans;
}

inline bool cmp(Data x,Data y){
	if(x.l!=y.l)
		return x.l<y.l;
	return x.r<y.r;
}

int ansx[MAXN],ansy[MAXN],ansnum;

int main(){
	n=read();
	for(int i=1;i<=n;++i)
		a[i].h=read(),a[i].l=read(),a[i].r=read(),--a[i].r;
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;++i){
		x[++cnt]=a[i].l;
		x[++cnt]=a[i].l+1;
		x[++cnt]=a[i].r;
		x[++cnt]=a[i].r+1;
	}
	x[0]=x[1]-1;
	sort(x+1,x+1+cnt);
	for(int i=1;i<=cnt;++i)
		if(x[i]!=x[i-1]) Map[x[i]]=++num,rev[num]=x[i];
	++num;
	for(int i=1;i<=n;++i)
		update(Map[a[i].l],Map[a[i].r],a[i].h);
	int last=0;
	for(int i=1;i<=num;++i){
		int tmp=query(i);
		if(tmp!=last){
			if(tmp>last){
				ansx[++ansnum]=rev[i],ansy[ansnum]=last;
				ansx[++ansnum]=rev[i],ansy[ansnum]=tmp;
			}
			else{
				ansx[++ansnum]=rev[i-1]+1,ansy[ansnum]=last;
				ansx[++ansnum]=rev[i-1]+1,ansy[ansnum]=tmp;
			}
			last=tmp;
		}
	}
	printf("%d\n",ansnum);
	for(int i=1;i<=ansnum;++i)
		printf("%d %d\n",ansx[i],ansy[i]);
	return 0;
}
posted @ 2019-11-11 11:51  yjk  阅读(169)  评论(0编辑  收藏  举报