[HNOI2012]三角形覆盖问题
题面
二维平面中,给定 \(N\) 个等腰直角三角形(每个三角形的两条直角边分别平行于坐标轴,斜边从左上到右下)。我们用三个非负整数 \((x, y, d)\) 来描述这样一个三角形,三角形三个顶点的坐标分别为 \((x, y), (x + d, y)\) 和 \((x, y + d)\) 。要求计算这 \(N\) 个三角形所覆盖的总面积。例如,下图有 \(3\) 个三角形,覆盖的总面积为 11.0。

输入格式:
输入文件第一行为一个正整数N,表示三角形的个数。
接下来的 \(N\) 行每行有用空格隔开的三个非负整数,\(x, y, d\) ,描述一个三角形的顶点坐标,分别为 \((x, y)\) , \((x + d, y)\) , \(( x, y+d)\) ,其中 \(x, y, d\) 满足 \(0<= x, y, d<=1000000\) 。
输出格式:
仅包含一行,为一个实数 \(S\) ,表示所有三角形所覆盖的总面积,输出恰好保留一位小数。输入数据保证 \(S\le 2^{31}\) 。
输入样例
3
1 1 4
2 0 2
3 2 2
输出样例
11.0
\(Solution:\)
显然扫描线,扫描线的做法因题而异,不同的题面有不同的写法。
这里给出链表+扫描线的方法:
先按 \(y\) 轴排序,然后从下扫描到上,因为坐标都是小于1e6的,所以直接暴力扫。
这题跟矩形面积并不一样,因为是等腰直角三角形,每次扫描线向上走一个单位,扫描线对应的地方覆盖就要少一。
数据结构:
- 双向链表
实际上是一个容器,存的是覆盖当前扫描线的三角形的编号,即如果编号为 \(i\) 的三角形覆盖了扫描线的一部分,那么 \(list[i]\) 就在链表中。
链表只是为了我们快速修改信息,插入和删除都是 \(O(1)\) 的, 查询信息也很方便。
- \(cover[x]\)
存储 ( \(x\) , 扫描线位置) 被多少个三角形覆盖,用来更新扫描线被覆盖的线段长度用。
算法流程:
- 按 \(y\) 轴排序。
- 从下往上扫描 \(i\) 记录扫描线的位置,\(j\) 记录当前有前 \(j\) 个在链表中或者已经处理完。
- 先统计链表中的答案 \(now\) ,并修改信息,记下 \(i-1\) 时的覆盖线段长,\(ans+= \frac{now+last}{2}\).
- 将新的三角形插进链表,更新 \(cover\) ,求出新的被覆盖线段长,记录到 \(last\) ,扫描线上移,执行 \(3\) 直至扫描完成。
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e5 + 20;
int n, mx;
struct Tri
{
int x, y, d, l, r;
Tri() {}
Tri(const int &_x, const int &_y, const int &_d)
{ x = _x, y = _y, d = _d, l = _x, r = _x + _d - 1;}
} tri[N];
inline bool cmp(const Tri &A, const Tri &B)
{ return A.y < B.y; }
namespace List
{
int head, tail, nxt[N], pre[N];
void Del(int x)
{
pre[nxt[x]] = pre[x];
nxt[pre[x]] = nxt[x];
}
void Ins(int x, int y)
{
pre[nxt[x]] = y;
nxt[y] = nxt[x];
nxt[x] = y;
pre[y] = x;
}
bool ins(int x)
{
if (tri[x].d == 0) return false;
Ins(head, x);
return true;
}
}
using namespace List;
int cover[(int)2e6 + 2];
int main()
{
cin >> n;
for (int i = 1; i <= n; ++ i)
{
int x, y, d;
cin >> x >> y >> d;
mx = max(mx, y + d);
tri[i] = Tri(x, y, d);
}
sort(tri + 1, tri + 1 + n, cmp);
head = 0; tail = n + 1;
nxt[head] = tail; pre[tail] = head;
int ans = 0, last = 0, now = 0;
for (int i = tri[1].y, j = 1; i <= mx; ++ i)
{
now = last;
for (int k = nxt[head]; k != tail; k = nxt[k])
{
-- cover[tri[k].r];
if (!cover[tri[k].r]) now--;
tri[k].r --;
if (tri[k].x > tri[k].r) Del(k);
}
ans += now + last;
while (j <= n && tri[j].y == i)
{
if (ins(j))
{
for (int k = tri[j].x; k < tri[j].x + tri[j].d; k ++)
{
if (!cover[k]) now ++;
cover[k] ++;
}
}
j ++;
}
last = now;
}
printf("%.1f\n", ans / 2.0);
}
[HNOI2012]三角形覆盖问题的更多相关文章
- BZOJ 2731 Luogu P3219 [HNOI2012]三角形覆盖问题 (扫描线)
题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=2731 (luogu)https://www.luogu.org/probl ...
- 【题解】三角形 [P1222] / 三角形覆盖问题 [HNOI2012] [P3219]
[题解]三角形 [P1222] / 三角形覆盖问题 [HNOI2012] [P3219] 传送门: 三角形 \(\text{[P1222]}\) 三角形覆盖问题 \(\text{[HNOI2012] ...
- 【BZOJ2731】三角形覆盖问题
想象一条平行于\(y\)轴的扫描线,从低往高扫描.如何确定关键高度才能使每两个关键高度之间分割出的图形易于计算呢? 关键高度有:三角形底边高度.三角形上顶点高度.三角形交点的高度. 如此分割,我们 ...
- [HNOI 2012]三角形覆盖问题
Description 二维平面中,给定 N个等腰直角三角形(每个三角形的两条直角边分别 平行于坐标轴,斜边从左上到右下).我们用三个非负整数( x, y, d)来描 述这样一个三角形 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- css实现的透明三角形
css实现下图样式,具体像素值记不住了,很好设置,html code (2014百度秋招面试题): <div id="demo"></div> 分析:这 ...
- 现代3D图形编程学习-设置三角形颜色(译)
本书系列 现代3D图形变成学习 http://www.cnblogs.com/grass-and-moon/category/920962.html 设置颜色 这一章会对上一章中绘制的三角形进行颜色的 ...
- HihoCoder1642 : 三角形面积和([Offer收割]编程练习赛37)(求面积)(扫描线||暴力)(占位)
描述 如下图所示,在X轴上方一共有N个等腰直角三角形.这些三角形的斜边与X轴重合,斜边的对顶点坐标是(Xi, Yi). (11,5) (4,4) /\ /\(7,3) \ / \/\/ \ / /\/ ...
- HihoCoder1652 : 三角形面积和2([Offer收割]编程练习赛38)(几何)(不会几何,占位)
描述 如下图所示,在X轴上方一共有N个三角形.这些三角形的底边与X轴重合,底边上两个顶点的坐标分别是(Li, 0)和(Ri, 0),底边的对顶点坐标是(Xi, Yi).其中Li ≤ Xi ≤ Ri 且 ...
随机推荐
- 【洛谷P1978】 集合
集合 题目链接 显然,我们是要把数据先排序的, 然后从大到小枚举每个数,看是否能选上, 能选就选,不能拉倒 若能,二分查找a[i]/k,若查找成功,ans++ 将a[i]/k标记为不能选择 最后输出答 ...
- 【luogu P1494 [国家集训队]小Z的袜子】 题解
题目链接:https://www.luogu.org/problemnew/show/P1494 #include <cstdio> #include <algorithm> ...
- 【Linux-CentOS】【转-更正】使用CentOS DVD1 和DVD2做本地yum源
原文在此.此文写的非常好,怕网络丢失,特转来,并做了更正. CentOS6以上版本一般都会提供一个DVD1和一个DVD2镜像,使用DVD1即可安装使用CentOS了,DVD2中存放了一些额外的软件包, ...
- C#基础 一(方法详解)
需要知道:类和方法的关系 方法和参数修饰符 自定义方法可以有或没有参数,也可以有或没有返回值.可以被各种关键字(static.virtual.public.new等)修饰以限制其行为. C#参数修饰符 ...
- Ionic的项目结构(angluar js)
Hybird HTML5 App(移动应用开发)之3.Ionic的项目结构 前面使用命令ionic start myapp下载了默认的Ionic应用程序,下面我们打开应用程序项目,来分析一下Ionic ...
- JS apply 和 call 的实现
很早之前的一篇博客写了bind的实现,是基于apply的,感兴趣的朋友看完这篇文章可以接着看看bind的实现. apply 和 call 主要就是传参的区别.这里就不多说了,直接看代码. //call ...
- MB/s与Mbit/s的区别
数据传输率的单位一般采用MB/s或Mbit/s,尤其在内部数据传输率上官方数据中更多的采用Mbit/s为单位.此处有必要讲解一下两个单位二者之间的差异: MB/s的含义是兆字节每秒,Mbit/s的含义 ...
- Vue+webpack构建一个项目
1.安装CLI命令的工具 推荐用淘宝的镜像 npm install -g @vue/cli @vue/cli-init 2.使用命令构建一个名为myapp的项目 vue init webpack m ...
- PHP-提升PHP性能的几个扩展
下面介绍的几个扩展原理都是对OPCODE进行缓存(Opcode缓存原理查看http://www.cnblogs.com/JohnABC/p/4531029.html): Zend Opcache: 由 ...
- 如何在hadoop中使用外部的python程序文件
业务场景大概是这样,我需要在公司hadoop集群上对博文进行结巴分词.我的数据是存储在hive表格中的,数据量涉及到五百万用户三个月内发的所有博文. 首先对于数据来说,很简单,在hive表格中就是两列 ...