题意:

有一个\(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. java网络访问指定出口ip

    java网络访问指定出口ip Table of Contents 1. socket 2. apache httpclient 1 socket 可以在Socket构造函数中指定使用的本地ip,如: ...

  2. This is your path and you will pursue it with excellence.

    This is your path and you will pursue it with excellence.自己选的路就要走出精彩.

  3. Eucalyptus-instance启动后查看运行状态

    1.前言 在eucalyptus中通过虚拟机模板,创建并启动一个虚拟机,这个时候虚拟机启动正常,但是外部一直无法访问也ping不通,正对这种情况我们如何检查排除问题呢? 两种检查问题的方法: 1).在 ...

  4. uvm_tlm——TLM1事务级建模方法(一)

    TLM(事务级建模方法,Transaction-level modeling)是一种高级的数字系统模型化方法,它将模型间的通信细节与函数单元或通信架构的细节分离开来.通信机制(如总线或者FIFO)被建 ...

  5. 根据accept-language自动设置UICulture和Culture

    在web.config中添加如下配置: <system.web> <globalization uiCulture="auto" culture="au ...

  6. 页面中插入视频兼容ie8以上的浏览器

    有时候页面中需要插入视频,如果不考虑ie8的话:就是直接用h5标签<video></video>就可以了: 但是有的时候需求是需要考虑ie8,这样我们就可以用插件,这种vide ...

  7. pat乙级1050螺旋矩阵

    1.用vector建立二维数组: vector<vector<int>> arr(rows); ; i < rows; i++) arr[i].resize(cols); ...

  8. linux 命令——31 /etc/group文件(转)

    Linux /etc/group文件与/etc/passwd和/etc/shadow文件都是有关于系统管理员对用户和用户组管理时相关的文件. linux /etc/group文件是有关于系统管理员对用 ...

  9. 自动释放池的前世今生 ---- 深入解析 autoreleasepool

    http://draveness.me/autoreleasepool.html 关注仓库,及时获得更新:iOS-Source-Code-Analyze Follow: Draveness · Git ...

  10. BZOJ 1229: [USACO2008 Nov]toy 玩具

    BZOJ 1229: [USACO2008 Nov]toy 玩具 标签(空格分隔): OI-BZOJ OI-三分 OI-双端队列 OI-贪心 Time Limit: 10 Sec Memory Lim ...