题面

二维平面中,给定 \(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的,所以直接暴力扫。

这题跟矩形面积并不一样,因为是等腰直角三角形,每次扫描线向上走一个单位,扫描线对应的地方覆盖就要少一。

数据结构:

  1. 双向链表

实际上是一个容器,存的是覆盖当前扫描线的三角形的编号,即如果编号为 \(i\) 的三角形覆盖了扫描线的一部分,那么 \(list[i]\) 就在链表中。

链表只是为了我们快速修改信息,插入和删除都是 \(O(1)\) 的, 查询信息也很方便。

  1. \(cover[x]\)

存储 ( \(x\) , 扫描线位置) 被多少个三角形覆盖,用来更新扫描线被覆盖的线段长度用。

算法流程:

  1. 按 \(y\) 轴排序。
  2. 从下往上扫描 \(i\) 记录扫描线的位置,\(j\) 记录当前有前 \(j\) 个在链表中或者已经处理完。
  3. 先统计链表中的答案 \(now\) ,并修改信息,记下 \(i-1\) 时的覆盖线段长,\(ans+= \frac{now+last}{2}\).
  4. 将新的三角形插进链表,更新 \(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]三角形覆盖问题的更多相关文章

  1. BZOJ 2731 Luogu P3219 [HNOI2012]三角形覆盖问题 (扫描线)

    题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=2731 (luogu)https://www.luogu.org/probl ...

  2. 【题解】三角形 [P1222] / 三角形覆盖问题 [HNOI2012] [P3219]

    [题解]三角形 [P1222] / 三角形覆盖问题 [HNOI2012] [P3219] 传送门: 三角形 \(\text{[P1222]}\) 三角形覆盖问题 \(\text{[HNOI2012] ...

  3. 【BZOJ2731】三角形覆盖问题

    想象一条平行于\(y\)轴的扫描线,从低往高扫描.如何确定关键高度才能使每两个关键高度之间分割出的图形易于计算呢? 关键高度有:三角形底边高度.三角形上顶点高度.三角形交点的高度. ​ 如此分割,我们 ...

  4. [HNOI 2012]三角形覆盖问题

    Description 二维平面中,给定   N个等腰直角三角形(每个三角形的两条直角边分别     平行于坐标轴,斜边从左上到右下).我们用三个非负整数( x, y, d)来描   述这样一个三角形 ...

  5. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  6. css实现的透明三角形

    css实现下图样式,具体像素值记不住了,很好设置,html code (2014百度秋招面试题): <div id="demo"></div>   分析:这 ...

  7. 现代3D图形编程学习-设置三角形颜色(译)

    本书系列 现代3D图形变成学习 http://www.cnblogs.com/grass-and-moon/category/920962.html 设置颜色 这一章会对上一章中绘制的三角形进行颜色的 ...

  8. HihoCoder1642 : 三角形面积和([Offer收割]编程练习赛37)(求面积)(扫描线||暴力)(占位)

    描述 如下图所示,在X轴上方一共有N个等腰直角三角形.这些三角形的斜边与X轴重合,斜边的对顶点坐标是(Xi, Yi). (11,5) (4,4) /\ /\(7,3) \ / \/\/ \ / /\/ ...

  9. HihoCoder1652 : 三角形面积和2([Offer收割]编程练习赛38)(几何)(不会几何,占位)

    描述 如下图所示,在X轴上方一共有N个三角形.这些三角形的底边与X轴重合,底边上两个顶点的坐标分别是(Li, 0)和(Ri, 0),底边的对顶点坐标是(Xi, Yi).其中Li ≤ Xi ≤ Ri 且 ...

随机推荐

  1. 2018年暑假ACM个人训练题9(动态规划)解题报告

    A:m段最大字段和问题 https://www.cnblogs.com/yinbiao/p/9314528.html B:map的使用(根本就不是dp!!!) https://www.cnblogs. ...

  2. python logging—模块

    python logging模块 python logging提供了标准的日志接口,python logging日志分为5个等级: debug(), info(), warning(), error( ...

  3. watch、computed、methods的区别

    1. `computed`属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算.主要当作属性来使用,要return出去一个值:2. `methods`方法表示一个具体的操作,主要书写业务逻辑:3. ...

  4. vue2.0移除或更改的一些东西

    一.vue2.0移除了$index和$key 虽然说现在很多文章说他们的代码是vue2.0版本的,但是有一些仔细一看,发现并不全是2.0版本,有些语法还是1.0的版本,比如这个$index,$key, ...

  5. [oracle]索引与索引表管理

    (一)索引的概念 索引是一种与表或簇相关的数据库对象,能够为数据的查询提供快捷的存取路径,减少磁盘I/O,提高检索效率. 索引由索引值及记录相应物理地址的ROWID两个部分构成,并按照索引值有序排列, ...

  6. Python基础—07-函数使用(01)

    #函数使用 零碎知识 灵活的if-else a = 3 if False else 5 # 等价于 if False: a = 3 else: a = 5 灵活的and/or # 当前面为真,才会进行 ...

  7. iptables防火墙常用命令参数

    iptable添加一条规则开放22端口 iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A OUTPUT -p tcp --sport ...

  8. Python核心框架tornado的异步协程的2种方式

    什么是异步? 含义 :双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始位,同时在结束时有停止位 现象:没有共同的时钟,不考虑顺序来了 ...

  9. js实现前端的搜索历史记录

    最近在对接前台页面(WEB端)时,产品要求需记录下客户的搜索记录,我们是前后台完全分离的项目,根本不能保存的session域中,没办法,虽然作为后台开发,遇到需求就自己研究了一通,先看一下最终效果图, ...

  10. wamp2.5怎么设置虚拟域名

    换了台电脑~好不顺手.老大的机器上装的是wamp.几年没用差点连怎么设置虚拟域名都忘记了.自己写点东西~做个备忘吧. 首先,版本 然后在网上百度一堆七七八八的.做的时候没那么复杂.跟phpstudy差 ...