码迷,mamicode.com
首页 > 其他好文 > 详细

P1382 楼房

时间:2019-02-01 14:14:55      阅读:227      评论:0      收藏:0      [点我收藏+]

标签:typedef   最大   show   math   判断   \n   rbegin   ==   ras   

传送门

在同一横坐标,轮廓只会被最高的楼房影响

所以考虑用 $multiset$ 维护当前的每个楼房高度

轮廓线显然只有出现楼房最高高度变化时会出现转折点

把一个楼根据左右边界分成两个东西,左边时把高度加入 $set$,到了右边再从 $set$ 里把该高度删除

每次更新 $set$ 时判断一下高度变化并记录答案就好了

注意每次插入或删除时要把同一横坐标的一起完成,因为同一横坐标最多只会产生一次贡献

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while(ch<0||ch>9) { if(ch==-) f=-1; ch=getchar(); }
    while(ch>=0&&ch<=9) { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
    return x*f;
}
const int N=1e6+7;
int n,m;
int ans[N][2],tot;
struct dat{
    int x,y;
    inline bool operator < (const dat &tmp) const {
        return x<tmp.x;
    }
}d[N];
multiset <int> S;
int main()
{
    int a,b,c;
    n=read();
    for(int i=1;i<=n;i++)
    {
        a=read(),b=read(),c=read();
        d[++m].x=b; d[m].y=a;
        d[++m].x=c; d[m].y=-a;//把楼房拆成两部分
    }
    sort(d+1,d+m+1);//按横坐标排序
    S.insert(0); int h=0,j=0,t=0;//h是当前高度
    for(int i=1;i<=m;)//从左到右一个个考虑
    {
        for(j=i;j<=m;j++)//要把同一横坐标的一起插入或删除
        {
            if(d[j].x>d[i].x) break;
            if(d[j].y>0) S.insert(d[j].y);
            else S.erase(S.find(-d[j].y));
        }
        t=(*S.rbegin());//rbegin指向集合最后一个数,即最大值
        if(t!=h)//有高度变化才能计算答案
        {
            ans[++tot][0]=d[i].x; ans[tot][1]=h;
            ans[++tot][0]=d[i].x; ans[tot][1]=t;
            h=t;
        }
        i=j;
    }
       printf("%d\n",tot);
       for(int i=1;i<=tot;i++) printf("%d %d\n",ans[i][0],ans[i][1]);
    return 0;
}

 

P1382 楼房

标签:typedef   最大   show   math   判断   \n   rbegin   ==   ras   

原文地址:https://www.cnblogs.com/LLTYYC/p/10345532.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!