[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 且 ...
随机推荐
- ADO.NET 之 Entity Framework 基础
Entity Framework(EF)是使用直接映射到应用程序中业务对象的对象模型于关系数据库进行交互.它没有将数据视为行和列的集合,而是将其视为强类型对象(成为实体)的集合. 术语:LinQ to ...
- C#中的代码书写规范以及命名规范
C#代码书写规则: 1. 尽量使用接口,然后使用类实现接口,以提高程序的灵活性. 2.一行不要超过80个字符 3.尽量不要手动更改计算机生成的代码 4.关键的语句写注释 5.建议局部变量在最接近使用它 ...
- deep learning学习记录一
最近不小心又赶了一下时髦,在做deep learning.今天去听了复旦吴老师的课程,感觉吴老讲解的还是很清晰的. 上午刚看过cnn,下午讲解的就是这章,相对来说,我听着给了很多启发.
- Openresty最佳案例 | 第5篇:http和C_json模块
转载请标明出处: http://blog.csdn.net/forezp/article/details/78616672 本文出自方志朋的博客 http客户端 Openresty没有提供默认的Htt ...
- Java秒杀系统方案优化 高性能高并发实战(已完成)
1:商品列表 2:商品详情判断是否可以开始秒杀,未开始不显示秒杀按钮显示倒计时,开始显示秒杀按钮,同时会显示验证码输入框以及验证码图片,当点击秒杀按钮的时候会首先判断验证码是否正确,如果正确会返回一个 ...
- C++创建学生类练习
/*作业,定义一个学生类*/ /*数据成员:学号.姓名.数学.英语.计算机三科成绩 *成员函数:求总成绩.求三科平均成绩.输出学生信息 *新增一个生日类 2018.4.2 */ #include &l ...
- 动态规划(二)HDU1114
1.题目来源HDU1114 Sample Input 3 10 110 2 1 1 30 50 10 110 2 1 1 50 30 1 6 2 10 3 20 4 Sample Output The ...
- Java Iterator ListIterator 理解
一. Iterator 常用操作 next hasNext remove 先上源码:JDK8 简化版本,用于说明问题 private class Itr implements Iterator< ...
- mysqldump备份与基于bin-log实现完全恢复
MySQL数据库备份是一项非常重要的工作,mysql的备份主要分为逻辑备份和物理备份,同时,不同的生产环境要备份的策略也不会不同.下面先说一说备份时要考虑到的一些因素,然后再实际操作进行不同方式的数据 ...
- php sign签名实例
1:实现签名代码: /** * 签名生成算法 * @param array $params API调用的请求参数集合的关联数组,不包含sign参数 * @param string $secret 签名 ...