zoukankan      html  css  js  c++  java
  • 洛谷 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
  • 相关阅读:
    类的内部成员之五-----内部类
    接口的使用
    java中abstract关键字的使用
    Redis主从复制原理——哨兵模式(Sentinel)
    Redis主从复制原理——薪火相传
    Redis主从复制原理——一主二仆
    Git---使用Github实现团队内协作操作步骤
    Final知识点总结
    代码块知识点总结
    Linux学习计划
  • 原文地址:https://www.cnblogs.com/DriverLao/p/8195552.html
Copyright © 2011-2022 走看看