codevs 2995 楼房

题目描述 Description

地平线(x轴)上有n个矩(lou)形(fang),用三个整数h[i],l[i],r[i]来表示第i个矩形:矩形左下角为(l[i],0),右上角为(r[i],h[i])。地平线高度为0。在轮廓线长度最小的前提下,从左到右输出轮廓线。

输入描述 Input Description

第一行一个整数n,表示矩形个数

以下n行,每行3个整数h[i],l[i],r[i]表示第i个矩形。

输出描述 Output Description

第一行一个整数m,表示节点个数

以下m行,每行一个坐标表示轮廓线上的节点。从左到右遍历轮廓线并顺序输出节点。第一个和最后一个节点的y坐标必然为0。

样例输入 Sample Input

【样例输入】

2
3 0 2
4 1 3

【样例输入2】

5
3 -3 0
2 -1 1
4 2 4
2 3 7
3 6 8

样例输出 Sample Output

【样例输出】

6
0 0
0 3
1 3
1 4
3 4
3 0

【样例输出2】

14
-3 0
-3 3
0 3
0 2
1 2
1 0
2 0
2 4
4 4
4 2
6 2
6 3
8 3
8 0

数据范围及提示 Data Size & Hint

对于30%的数据,n<=100

对于另外30%的数据,n<=100000,1<=h[i],l[i],r[i]<=1000

对于100%的数据,1<=n<=100000,1<=h[i]<=10^9,-10^9<=l[i]<r[i]<=10^9

先把数据横坐标离散化

线段树维护每一列的高度最大值

注意 楼房区间[l,r],线段树更改的区间为[l,r-1]

发现对于每一列,先输出(x,上一条边的y),再输出(x,这一条边的y)

#include<algorithm>
#include<cstdio>
#include<queue>
#define N 100001
using namespace std;
int xi[N],yi[N],h[N],hash[2*N],cnt;
int n,maxn[N*8],opl,opr,w,ans;
int f[N*8],out1[N*4],out2[N*4],tot;
struct TREE
{
    void down(int k)
    {
        maxn[k<<1]=max(maxn[k<<1],f[k]);
        maxn[k<<1|1]=max(maxn[k<<1|1],f[k]);
        f[k<<1]=max(f[k<<1],f[k]);
        f[k<<1|1]=max(f[k<<1|1],f[k]);
        f[k]=0;
    }
    void solve(int k,int l,int r,int p)
    {
        if(l>=opl&&r<=opr)
        {
            if(p==1)
            {
                maxn[k]=max(maxn[k],w);
                f[k]=max(f[k],w);    
            }
            else ans=maxn[k];
            return ;
        }
        if(f[k]) down(k);
        int mid=l+r>>1;
        if(opl<=mid) solve(k<<1,l,mid,p);
        if(opr>mid) solve(k<<1|1,mid+1,r,p);
        if(p==1) maxn[k]=max(maxn[k<<1],maxn[k<<1|1]);
    }
}tr;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&h[i]);
        scanf("%d%d",&xi[i],&yi[i]);
        hash[i*2-1]=xi[i]; hash[i*2]=yi[i];
    }
    sort(hash+1,hash+2*n+1);
    cnt=unique(hash+1,hash+2*n+1)-(hash+1);
    for(int i=1;i<=n;i++)
    {
        opl=lower_bound(hash+1,hash+cnt+1,xi[i])-hash;
        opr=lower_bound(hash+1,hash+cnt+1,yi[i])-hash-1;
        w=h[i];
        tr.solve(1,1,cnt,1);
    }
    int last=0;
    for(int i=1;i<=cnt;i++)
    {
        opl=opr=i;
        tr.solve(1,1,cnt,2);
        if(ans!=last)
        {
            out1[++tot]=hash[i]; out2[tot]=last;
            out1[++tot]=hash[i]; out2[tot]=ans;
            last=ans;
        }
    }
    printf("%d
",tot);
    for(int i=1;i<=tot;i++) printf("%d %d
",out1[i],out2[i]);
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/6828982.html