洛谷 1382 楼房

【题解】

  本题要计算矩形组成的轮廓线,可以用线段树来实现。

  由于区间长度很大,不能直接开线段数记录,我们要先进行离散化。(显然拐点只可能出现在矩形的左右两边上)然后逐个加入矩形并维护每个位置的最大值。最后对每个拐点可能的位置进行查询并统计答案即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define ls (u<<1)
 4 #define rs (u<<1|1)
 5 #define mid ((a[u].l+a[u].r)>>1)
 6 using namespace std;
 7 const int maxn=800010;
 8 int n,N,m,h[maxn],l[maxn],r[maxn],l0[maxn],r0[maxn],s[maxn];
 9 struct tree{int l,r,max,del;}a[maxn];
10 struct point{int x,y;}ans[maxn];
11 inline int read(){
12     int k=0,f=1; char c=getchar();
13     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
14     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
15     return k*f;
16 }
17 void build(int u,int l,int r){
18     a[u].l=l; a[u].r=r; a[u].max=0;
19     if(l<r) build(ls,l,mid),build(rs,mid+1,r);
20 }
21 void pushdown(int u){
22     a[ls].max=max(a[ls].max,a[u].del); a[rs].max=max(a[rs].max,a[u].del); 
23     a[ls].del=max(a[ls].del,a[u].del); a[rs].del=max(a[rs].del,a[u].del); a[u].del=0;
24 }
25 void update(int u,int l,int r,int del){
26     if(l<=a[u].l&&a[u].r<=r){a[u].max=max(a[u].max,del); a[u].del=max(a[u].del,del); return;}
27     pushdown(u);
28     if(l<=mid) update(ls,l,r,del);
29     if(r>mid) update(rs,l,r,del);
30     a[u].max=max(a[ls].max,a[rs].max);
31 }
32 int query(int u,int pos){
33     if(a[u].l==a[u].r) return a[u].max;
34     pushdown(u);
35     if(pos<=mid) return query(ls,pos); else return query(rs,pos);
36 }
37 inline void Prepare(){
38     m=read();
39     for(int i=1;i<=m;i++) h[i]=read(),s[++n]=l0[i]=read(),s[++n]=r0[i]=read();
40     sort(s+1,s+1+n); N=unique(s+1,s+1+n)-s-1;
41     for(int i=1;i<=m;i++)
42         l[i]=lower_bound(s+1,s+1+N,l0[i])-s,
43         r[i]=lower_bound(s+1,s+1+N,r0[i])-s;
44 }
45 int main(){
46     Prepare(); build(1,1,N+1);
47     for(int i=1;i<=m;i++) update(1,l[i],r[i]-1,h[i]);
48 //    for(int i=1;i<=N+1;i++) printf("%d
",query(1,i));
49     int last=0,tot=0;
50     for(int i=1;i<=N+1;i++){
51         int now=query(1,i);
52         if(now!=last){
53             ans[++tot]=(point){s[i],last};
54             ans[++tot]=(point){s[i],now};
55         }
56         last=now;
57     }
58     printf("%d
",tot);
59     for(int i=1;i<=tot;i++) printf("%d %d
",ans[i].x,ans[i].y);
60     return 0;
61 }
View Code
原文地址:https://www.cnblogs.com/DriverLao/p/8195552.html