这个题先离散化,然后强行用线段树统计每个点的高度,就可以了,只需要区间修改和单点查询就好,不过数据范围可能是假的……因为题目100000,然后我按照线段树开了4倍空间,然后re了,直到开了8倍……
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; int m; struct es { int h,x,y; }ing[200010]; struct in { int l,r,mx,add; }ter[800040]; int a[800020],len,tot,a1[1000020],a2[1000020]; inline void build(int l,int r,int w) { ter[w].mx=0,ter[w].l=l,ter[w].r=r,ter[w].add=0; if(l==r) return; int mid=l+r>>1; build(l,mid,w<<1),build(mid+1,r,w<<1|1); } inline void d(int w) { if(!ter[w].add) return; ter[w<<1].mx=max(ter[w<<1].mx,ter[w].add); ter[w<<1|1].mx=max(ter[w<<1|1].mx,ter[w].add); ter[w<<1].add=max(ter[w].add,ter[w<<1].add); ter[w<<1|1].add=max(ter[w].add,ter[w<<1|1].add); ter[w].add=0; } inline void u(int w) { ter[w].mx=max(ter[w<<1].mx,ter[w<<1|1].mx); } void cha(int l,int r,int x,int w)//区间修改赋值 { if(ter[w].l==l&&ter[w].r==r) { ter[w].mx=max(ter[w].mx,x),ter[w].add=max(ter[w].add,x);return; } d(w); int mid=ter[w].l+ter[w].r>>1; if(r<=mid) cha(l,r,x,w<<1); else if(l>mid) cha(l,r,x,w<<1|1); else cha(l,mid,x,w<<1),cha(mid+1,r,x,w<<1|1); u(w); } inline int ask(int l,int w)//单点查询 { if(l==ter[w].l&&l==ter[w].r) return ter[w].mx; d(w); int re=0,mid=ter[w].l+ter[w].r>>1; if(l<=mid) re=ask(l,w<<1); else re=ask(l,w<<1|1); u(w); return re; } int main() { scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&ing[i].h,&ing[i].x,&ing[i].y),a[i*2-1]=ing[i].x,a[i*2]=ing[i].y; sort(a+1,a+1+m*2);//排序,之后离散化 int len=unique(a+1,a+1+m*2)-a-1; build(1,len,1); for(int i=1;i<=m;i++) { int x=lower_bound(a+1,a+1+len,ing[i].x)-a; int y=lower_bound(a+1,a+1+len,ing[i].y)-a; cha(x,y-1,ing[i].h,1);//因为处理的是区间,有i个点就有i-1个区间 }//因为对答案有影响的只有矩形的两端,所以统计答案的时候只关心她们就好 for(int i=1;i<=len;i++) { a1[i]=a[i],a2[i]=ask(i,1);//询问高度 if(a2[i]!=a2[i-1]) tot++; } printf("%d\n",tot*2); for(int i=1;i<=len;i++) if(a2[i]!=a2[i-1])//如果高度产生落差,说明这是答案的之一 { printf("%d %d\n",a1[i],a2[i-1]); printf("%d %d\n",a1[i],a2[i]); } }
原文:http://www.cnblogs.com/Loi-dfkdsmbd/p/7748377.html