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\n",tot);
    for(int i=1;i<=tot;i++) printf("%d %d\n",out1[i],out2[i]);
}
时间: 2024-12-15 01:52:05

codevs 2995 楼房的相关文章

AC日记——楼房 codevs 2995

2995 楼房 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 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

bzoj 2957: 楼房重建.

2957: 楼房重建 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2303  Solved: 1088[Submit][Status][Discuss] Description 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上的房子拆了又建.建了又拆.他经常无聊地看着窗外发呆,数自己能够看到多少栋房子. 为了简化问题,我们考虑这些事件发生在一个二维平面上.小A在平面上(0,0)点的位置,第i栋楼房可以用一条连接(i,0)和

[ CodeVS冲杯之路 ] P2492

不充钱,你怎么AC? 题目:http://codevs.cn/problem/2492/ 在此先orz小胖子,教我怎么路径压缩链表,那么这样就可以在任意节点跳进链表啦(手动@LCF) 对于查询操作,直接树状数组(以下简称BIT)维护,修改操作就一个个暴力开方搞,再用差值单点更新BIT 不过这样会TLE,要加一点优化对不对,正如开头所说的路径压缩链表 路径压缩链表其实就是个并查集,在普通的链表里,删去两个连续的节点后会是下面这种情况,如删去2,3 当访问 2 的时候,会跳到3,但 3 已经删除了,

[CODEVS 1281] Xn数列

描述 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn http://codevs.cn/problem/1281/ 分析 比较裸的矩阵乘法题, 好久没做了, 写写思路 假设矩阵 A = { {a1, a2}, {a3, a4} }, B = { {b1, b2}, {b3, b4} }. 根据矩阵乘法的计算方法, 有 : A×B = { {a1b1+a2b2, a1b2+a2b4}, {a3b1+a4b3, a3b2+a4b4} }. 那

Codevs 1257 打砖块

1257 打砖块 http://codevs.cn/problem/1257/ 题目描述 Description 在一个凹槽中放置了n层砖块,最上面的一层有n块砖,第二层有n-1块,……最下面一层仅有一块砖.第i层的砖块从左至右编号为1,2,……i,第i层的第j块砖有一个价值a[i,j](a[i,j]<=50).下面是一个有5层砖块的例子.如果你要敲掉第i层的第j块砖的话,若i=1,你可以直接敲掉它,若i>1,则你必须先敲掉第i-1层的第j和第j+1块砖. 你的任务是从一个有n(n<=5

codevs——T1219 骑士游历

 http://codevs.cn/problem/1219/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个

1683 车厢重组 codevs

http://codevs.cn/problem/1683/ 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 题目描述 Description 在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转.一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序.于是他就负责用这座桥将进站的车厢按车厢号从小到大排列.他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序

codevs 1487 大批整数排序(水题日常)

时间限制: 3 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题目描述 Description !!!CodeVS开发者有话说: codevs自从换了评测机,新评测机的内存计算机制发生变化 计算内存的时候会包括栈空间 swap空间 这题的2M是单指内存空间... 十分十分抱歉 抱歉 !!! 现在有一大批(总数不超过10000000个)1到10之间的整数,现在请你从小到大进行排序输出. (测试数据将超过11MB.) 输入描述 Input Description 第一行表示将下排序

codevs 3342 绿色通道 (二分+线性DP)

codevs 3342 绿色通道 http://codevs.cn/problem/3342/ 难度等级:黄金 题目描述 Description <思远高考绿色通道>(Green Passage, GP)是唐山一中常用的练习册之一,其题量之大深受lsz等许多oiers的痛恨,其中又以数学绿色通道为最.2007年某月某日,soon-if (数学课代表),又一次宣布收这本作业,而lsz还一点也没有写…… 高二数学<绿色通道>总共有n道题目要写(其实是抄),编号1..n,抄每道题所花时间