Luogu1904 天际线

原题链接:https://www.luogu.com.cn/problem/P1904

天际线

题目描述

Latium 省的 Genoa 是亚平宁半岛西海岸北端的一片土地,自然资源丰富,却无人居住。你受到罗马执政官 Caesar 的委任,前往 Genoa 建立新的城市。Caesar 对这次任务的要求是在 Genoa 这片土地上建立起一座繁荣的城市,他将以此作为衡量你的表现的标准。

正在你大刀阔斧地进行城市建设的时候,Caesar 突然写信给你,说他要检查 Genoa 的建设情况。Caesar 希望知道你的城市是什么样子,但是他又非常的忙,所以他只要你描述一下城市的轮廓就可以了,他将依照城市的轮廓决定你的薪水。

怎样描述一个城市的轮廓呢?我们知道 Genoa 所有的建筑共享一个地面,你可以认为它是水平的。所有的建筑用一个三元组 ( L i , H i , R i ) (L_i,H_i,R_i) (Li,Hi,Ri),其中 L i L_i Li R i R_i Ri 分别是建筑的左坐标和右坐标, H i H_i Hi 就是建筑的高度。在下方所示的图表中左边建筑物描述如下 ( 1 , 11 , 5 ) (1,11,5) (1,11,5) ( 2 , 6 , 7 ) (2,6,7) (2,6,7) ( 3 , 13 , 9 ) (3,13,9) (3,13,9) ( 12 , 7 , 16 ) (12,7,16) (12,7,16) ( 14 , 3 , 25 ) (14,3,25) (14,3,25) ( 19 , 18 , 22 ) (19,18,22) (19,18,22) ( 23 , 13 , 29 ) (23,13,29) (23,13,29) ( 24 , 4 , 28 ) (24,4,28) (24,4,28),右边用轮廓线的顺序 ( 1 , 11 , 3 , 13 , 9 , 0 , 12 , 7 , 16 , 3 , 19 , 18 , 22 , 3 , 23 , 13 , 29 , 0 ) (1,11,3,13,9,0,12,7,16,3,19,18,22,3,23,13,29,0) (1,11,3,13,9,0,12,7,16,3,19,18,22,3,23,13,29,0) 表示:

在这里插入图片描述

输入格式

在输入数据中,你将得到一系列表示建筑的三元组。在输入数据中所有建筑的坐标中的数值都是小于 10000 10000 10000 的正整数,且至少有 1 1 1 幢建筑,最多有 5000 5000 5000 幢建筑。在输入输入中每幢建筑的三元组各占一行。三元组中的所有整数应由一个或多个空格分开。

输出格式

在输出数据中,你被要求给出城市的轮廓线。你可以这样来描述:对于所有轮廓线上的折点,按顺序排好,第奇数个点输出 x x x 坐标,第偶数个点输出 y y y 坐标,两个数之间用空格分开。

输入输出样例

输入 #1
1 11 5
2 6 7
3 13 9
12 7 16
14 3 25
19 18 22
23 13 29
24 4 28
输出 #1
1 11 3 13 9 0 12 7 16 3 19 18 22 3 23 13 29 0

题解

矩形面积并的代码一码三用……

把横向排列的矩形反转一下,就可以套用之前的模型:
在这里插入图片描述
同时因为矩形左边在同一竖直线上,所以任意时刻的截线都只会是一根完整的线段,我们直接统计被覆盖线段的总长就行了。

当出现有重合的边的时候,记得把所有重合边都添加/删去完再进行统计,一下是一组测试数据:

1 2 2
1 1 2

代码

为了方便边界处理,人为的规定所有边的左端点横坐标为 1 1 1

#include<bits/stdc++.h>
#define ls v<<1
#define rs v<<1|1
using namespace std;
const int M=5005;
struct Edge{
    
    
    int le,ri,h,val;
}edge[M<<1];
bool cmp(Edge a,Edge b){
    
    return a.h<b.h;}
struct node{
    
    
    int le,ri,len,cov;
}tree[M<<2];
int n,tot,x[M],cot,ans[M];
void up(int v){
    
    tree[v].len=tree[v].cov?tree[v].ri-tree[v].le:tree[ls].len+tree[rs].len;}
void build(int v,int le,int ri)
{
    
    
    tree[v].le=x[le],tree[v].ri=x[ri+1];
    if(le==ri)return;
    int mid=le+ri>>1;
    build(ls,le,mid),build(rs,mid+1,ri);
}
void cover(int v,int le,int ri,int val)
{
    
    
    if(le<=tree[v].le&&tree[v].ri<=ri)
    {
    
    
        tree[v].cov+=val;up(v);
        return;
    }
    if(le<tree[ls].ri)cover(ls,le,ri,val);
    if(tree[rs].le<ri)cover(rs,le,ri,val);
    up(v);
}
void in()
{
    
    
    x[++tot]=1;
    for(int a,b,c;~scanf("%d%d%d",&a,&b,&c);++n)
    edge[++cot]=(Edge){
    
    1,b+1,a,1},edge[++cot]=(Edge){
    
    1,b+1,c,-1},x[++tot]=b+1;
}
void ac()
{
    
    
    sort(x+1,x+1+tot);
    tot=unique(x+1,x+1+tot)-x-1;
    build(1,1,tot-1);
    sort(edge+1,edge+1+cot,cmp);
    //for(int i=1;i<=cot;++i)printf("%d %d %d %d\n",edge[i].le,edge[i].ri,edge[i].h,edge[i].val);
    for(int i=1,pre=0;i<=cot;++i)
    {
    
    
        for(;edge[i].h==edge[i+1].h;++i)cover(1,edge[i].le,edge[i].ri,edge[i].val);
        cover(1,edge[i].le,edge[i].ri,edge[i].val);
        if(tree[1].len!=pre)printf("%d %d ",edge[i].h,tree[1].len),pre=tree[1].len;
    }
}
int main()
{
    
    
    in(),ac();
    system("pause");
}

猜你喜欢

转载自blog.csdn.net/ShadyPi/article/details/113594741