题意:

有一个\(h \times w\)的矩形,其中有\(n\)个水平的障碍。从上往下扔一个小球,遇到障碍后会分裂成两个,分别从障碍的两边继续往下落。

如果从太高的地方落下来,障碍会消失。

问从每一列的上方扔一个小球,最终落到下面有多少个球。

分析:

每一个障碍对应一个矩形,也就是它的有效范围,在这个范围内下落的球才会落到上面,否则障碍会消失。

维护一条从下往上的扫描线,用线段树维护\([1,w]\)区间内被障碍覆盖的集合。

在扫描的过程中计算出对每个障碍一个球落在上面最终会形成多少个球,这可以通过在线段树中查询所在区间中最高的障碍来递推。

扫描结束后,也可以用同样的方法求出每个位置落下最终形成的球数。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std; const int maxn = 100000 + 10;
const int maxnode = maxn << 2;
const int MOD = 1000000007; int h, w, n; struct Barrier
{
int l, r, h, s; void read() { scanf("%d%d%d%d", &h, &l, &r, &s); }
}; struct Event
{
int height, type, id; bool operator < (const Event& t) const {
return height < t.height || (height == t.height && type < t.type);
}
}; struct Node
{
int h, id;
bool operator < (const Node t) const {
return h > t.h;
}
}; Barrier barriers[maxn];
Event events[maxn << 1];
set<Node> S[maxnode];
int cnt[maxn], ans[maxn]; void add(int& a, int b) { a += b; if(a >= MOD) a -= MOD; } int op, id, height; void opt(int o, int L, int R, int qL, int qR) {
if(qL <= L && R <= qR) {
if(op == 0) S[o].erase((Node){ height, id });
else S[o].insert((Node){ height, id });
return;
}
int M = (L + R) / 2;
if(qL <= M) opt(o<<1, L, M, qL, qR);
if(qR > M) opt(o<<1|1, M+1, R, qL, qR);
} Node qans;
void query(int o, int L, int R, int p) {
if(!S[o].empty()) { Node tmp = *S[o].begin(); if(tmp < qans) qans = tmp; }
if(L == R) return;
int M = (L + R) / 2;
if(p <= M) query(o<<1, L, M, p);
else query(o<<1|1, M+1, R, p);
} int query(int p)
{
qans = (Node){ -1, -1 };
query(1, 1, w, p);
if(qans.id == -1) return 1;
else return ans[qans.id];
} int main()
{
int tot = 0;
scanf("%d%d%d", &h, &w, &n);
for(int i = 0; i < n; i++) {
Barrier& b = barriers[i];
b.read();
events[tot++] = (Event){ b.h, 1, i };
if(b.h + b.s <= h) events[tot++] = (Event){ b.h + b.s + 1, -1, i };
}
sort(events, events + tot);
for(int i = 0; i < tot; i++) {
id = events[i].id;
Barrier& b = barriers[id];
if(events[i].type == -1) {
op = 0; height = b.h;
opt(1, 1, w, b.l, b.r);
} else {
if(b.l == 1) ans[id] = query(b.r + 1) * 2 % MOD;
else if(b.r == w) ans[id] = query(b.l - 1) * 2 % MOD;
else ans[id] = (query(b.l - 1) + query(b.r + 1)) % MOD;
op = 1; height = b.h;
opt(1, 1, w, b.l, b.r);
}
} int res = 0;
for(int i = 1; i <= w; i++) add(res, query(i));
printf("%d\n", res); return 0;
}

CodeForces 781E Andryusha and Nervous Barriers 线段树 扫描线的更多相关文章

  1. Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF781E.html 题目传送门 - CF781E 题意 有一个矩形,宽为 w ,高为 h .一开始会有 w 个 ...

  2. codeforces#1108E2. Array and Segments (线段树+扫描线)

    题目链接: http://codeforces.com/contest/1108/problem/E2 题意: 给出$n$个数和$m$个操作 每个操作是下标为$l$到$r$的数减一 选出某些操作,使$ ...

  3. Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)

    题目链接:http://codeforces.com/contest/522/problem/D 题目大意:  给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...

  4. [Codeforces 266E]More Queries to Array...(线段树+二项式定理)

    [Codeforces 266E]More Queries to Array...(线段树+二项式定理) 题面 维护一个长度为\(n\)的序列\(a\),\(m\)个操作 区间赋值为\(x\) 查询\ ...

  5. [Codeforces 280D]k-Maximum Subsequence Sum(线段树)

    [Codeforces 280D]k-Maximum Subsequence Sum(线段树) 题面 给出一个序列,序列里面的数有正有负,有两种操作 1.单点修改 2.区间查询,在区间中选出至多k个不 ...

  6. codeforces 1217E E. Sum Queries? (线段树

    codeforces 1217E E. Sum Queries? (线段树 传送门:https://codeforces.com/contest/1217/problem/E 题意: n个数,m次询问 ...

  7. 51nod 1494 选举拉票 (线段树+扫描线)

    1494 选举拉票  题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 现在你要竞选一个县的县长.你去对每一个选民进 ...

  8. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  9. 【POJ-2482】Stars in your window 线段树 + 扫描线

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11706   Accepted:  ...

随机推荐

  1. jQuery学习笔记(三)

    jQuery中的事件 页面加载 原生DOM中的事件具有页面加载的内容onload事件,在jQuery中同样提供了对应的内容ready()函数. ready与onload之间的区别: onload re ...

  2. 比例缩放 on() prop() 正则表达式

    $('#banner-section').css('height',$(window).width() / 1900 * 490 ); $(window).resize(function(){    ...

  3. Web前端开发的学习过程

    2018年 5月27日 开始在MDN上学习HTML/CSS/JavaScript.——6月18日 基本学完MDN的“学习Web开发”的HTML/CSS/JavaScript部分. 6月9日 开始在IF ...

  4. web端 css hack(一)

    逢10月小长假,几天不敲键盘,浑身难受.也是有时间分享一下自己遇到的css问题.先说一下什么css hack 简单介绍一下css hack: 定义: 一般都是利用各浏览器的支持CSS的能力和BUG来进 ...

  5. 合理设置apache的最大连接数

    手头有一个网站在线人数增多,访问时很慢.初步认为是服务器资源不足了,但经反复测试,一旦连接上,不断点击同一个页面上不同的链接,都能迅速打开,这种现象就是说明apache最大连接数已经满了,新的访客只能 ...

  6. freebsd开启root远程登陆

    i /etc/ssh/sshd_config 找到: #PermitRootLogin no改在: PermitRootLogin yes

  7. HDU 1011 Starship Troopers星河战队(树形dp)

    题意 有n个洞穴编号为1-n,洞穴间有通道,形成了一个n-1条边的树, 洞穴的入口即根节点是1. 每个洞穴有x只bugs,并有价值y的金子,全部消灭完一个洞穴的虫子,就可以获得这个洞穴的y个金子. 现 ...

  8. HDU3973 线段树 + 字符哈希

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3973 , 线段树 + 字符哈希,好题. 又学了一种新的哈希方法,hhhh~ 解法: 想法是用P进制的数 ...

  9. BZOJ 3873: [Ahoi2014]拼图

    BZOJ 3873: [Ahoi2014]拼图 标签(空格分隔): OI-BZOJ OI-DP Time Limit: 10 Sec Memory Limit: 256 MB Description ...

  10. python_72_json序列化2

    #序列化(json是最正规的) import json info={ 'name':'Xue Jingjie', 'age':22 } f=open('第72.text','w') print(jso ...