题意:给你n个建筑的楼顶的高度,以及楼顶的左坐标l,右坐标r(可以看成是线段),问整个建筑的轮廓的转折点。
易得,当两个建筑和交叉的部分时,那么显现出的轮廓的,一定是比较高的那个建筑,那么我们在线段树中放下每个线段,重叠部分取较大值,然后遍历线段树中的每个叶子结点,如果与前一个结点的高度不同,那么就一定是出现了转折。
l与r很大,要用离散化。
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <map> #include <algorithm> using namespace std; const int N=1e5+5; #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define MID(a,b) (a+((b-a)>>1)) vector<int> X; map<int,int> H; struct OP { int l,r,h; void get() { scanf("%d%d%d",&h,&l,&r); X.push_back(l); X.push_back(r); } }op[N]; struct Segtree { struct node { int lft,rht,mx; int mid(){return MID(lft,rht);} void fun(int h) { mx=max(mx,h);} }tree[N*8]; void PushDown(int ind) { if(tree[ind].mx) { tree[LL(ind)].fun(tree[ind].mx); tree[RR(ind)].fun(tree[ind].mx); tree[ind].mx=0; } } void build(int lft,int rht,int ind) { tree[ind].lft=lft; tree[ind].rht=rht; tree[ind].mx=0; if(lft+1!=rht) { int mid=tree[ind].mid(); build(lft,mid,LL(ind)); build(mid,rht,RR(ind)); } } void updata(int st,int ed,int ind,int h) { int lft=tree[ind].lft,rht=tree[ind].rht; if(st<=lft&&rht<=ed) tree[ind].fun(h); else { PushDown(ind); int mid=tree[ind].mid(); if(st<mid) updata(st,ed,LL(ind),h); if(ed>mid) updata(st,ed,RR(ind),h); } } int query(int st,int ed,int ind) { if(tree[ind].lft+1==tree[ind].rht) return tree[ind].mx; else { PushDown(ind); int mid=tree[ind].mid(),mx=0; if(st<mid) mx=query(st,ed,LL(ind)); else mx=query(st,ed,RR(ind)); return mx; } } }seg; int main() { int n; while(scanf("%d",&n)!=EOF) { X.clear(); H.clear(); for(int i=0;i<n;i++) op[i].get(); sort(X.begin(),X.end()); X.erase(unique(X.begin(),X.end()),X.end()); int len=(int)X.size(); for(int i=0;i<len;i++) H[X[i]]=i; seg.build(0,len-1,1); for(int i=0;i<n;i++) seg.updata(H[op[i].l],H[op[i].r],1,op[i].h); vector<pair<int,int> > res; int x=X[0],y=0; for(int i=0;i<len-1;i++) { int tmpy=seg.query(i,i+1,1); if(tmpy==y) continue; res.push_back(make_pair(X[i],y)); res.push_back(make_pair(X[i],tmpy)); y=tmpy; } if(y!=0) { res.push_back(make_pair(X[len-1],y)); res.push_back(make_pair(X[len-1],0)); } printf("%d\n",(int)res.size()); for(int i=0;i<(int)res.size();i++) printf("%d %d\n",res[i].first,res[i].second); } return 0; }