题意:

有一个\(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. UICollectionView笔记1

    WWDC 2012 Session笔记——205 Introducing Collection Views 这是博主的WWDC2012笔记系列中的一篇,完整的笔记列表可以参看这里.如果您是首次来到本站 ...

  2. sass相关随笔

    安装 下载ruby并且安装 点击这里 打开命令行输入 gem install sass 我使用的是sublime text3 还需要下载三个插件 sass -- 可以帮助你语法高亮 sass buil ...

  3. Android 悬浮窗权限各机型各系统适配大全

    这篇博客主要介绍的是 Android 主流各种机型和各种版本的悬浮窗权限适配,但是由于碎片化的问题,所以在适配方面也无法做到完全的主流机型适配,这个需要大家的一起努力,这个博客的名字永远都是一个将来时 ...

  4. javascript设计模式之中介者模式

    /* * 小游戏演示中介者模式 * Home 按键 1 * Guest 按键 0 * 半分钟内看谁按下的次数多 * * 参与的对象: * 玩家 * 计分板 * 中介者 * * 中介者模式使对象之间松耦 ...

  5. 逐步解读String类(一)

    一句题外话 面试刚入行的Java新手,侧重基础知识:面试有多年工作经验的老鸟,多侧重对具体问题的解决策略. 从一类面试题说起 考察刚入行菜鸟对基础知识的掌握程度,面试官提出关于String类的内容挺常 ...

  6. vue指令总结(二)

    一.vue指令 1.v-text v-text是用于操作纯文本,它会替代显示对应的数据对象上的值.当绑定的数据对象上的值发生改变,插值处的内容也会随之更新.注意:此处为单向绑定,数据对象上的值改变,插 ...

  7. gitlab用户添加ssh免密钥认证后clone还是要求输入密码

    今天在centos 7公网服务器上安装gitlab在配置ssh免密钥时遇到一个奇怪的事,正确添加了本机的公钥到gitlab账户上,进行clone时死活都要你输入密码gitlab使用yum安装的,之前在 ...

  8. Python 随笔之Redis

    Python学习记录 ——redis 2018-03-07 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从 ...

  9. java 串口通信实现流程

    1.下载64位rxtx for java 链接:http://fizzed.com/oss/rxtx-for-java 2.下载下来的包解压后按照说明放到JAVA_HOME即JAVA的安装路径下面去 ...

  10. 最好的 6 个 HTML5 的多媒体播放器

      是 HTML5 中新引入的标签,用来在 Web 网页中嵌入视频播放功能,无需 Flash 和其他嵌入式插件的支持,是浏览器内建的功能,不过  旨在一些高级浏览器中支持,例如 Firefox, Sa ...