题意:

有一个\(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. vue-实现一个购物车结算页面

    这是路由之间的跳转,传递值最好采用传参,而不是用$emit和$on,不起作用 如果实在一个页面中的兄弟组件,可以使用$emit和$on 中间件,eventBus.js 放在components目录下面 ...

  2. 【Quartus错误】Internal Error: Sub-system: AMERGE

    错误内容:Internal Error: Sub-system: AMERGE, File: /quartus/atm/amerge/amerge_kpt_op.cpp, Line: 220 解决方案 ...

  3. pysnmp程序

    功能 访问远程交换机snmp数据,写入本地influxdb数据库 #!/usr/bin/env python # -*- encoding: utf-8 -*- import os, yaml, ti ...

  4. C#访问修改符

    修饰符可以指定访问的可见性,还可以指定其本质.(文章摘自<C#高级编程(第9版)>以及Microsoft) 1. 可见性修饰符 public:应用于所有类型或成员,即任何代码均可以访问该项 ...

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

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

  6. HDU 1008 电梯( 水题)

    题意: 电梯当前在0层,每在1层需要停5秒,往上走每层需6秒,往下走每层需要4秒. 思路: 在接收输入的时候直接计算了它,不用再弄一个循环.每计算一个请求就更新当前层,停留5秒的等到输出时再加上5*n ...

  7. fpga 状态机 检测1011序列

    1011 可以使用4个状态:s0,s1,s2,s3. 即:(1)s0有0或1两个状态,当s0位0时,进入s0状态,自身打圈.为1那么进入下个状态s1来检测0. (2)s1有0或1两种情况,s1为1时s ...

  8. Python爬虫实战:爬糗事百科的段子

    一个偶然的机会接触了Python,感觉很好用,但是一直在看c++啥的,也没系统学习.用过之后也荒废了许久.之前想建个公众号自动爬糗事百科的段子,但是没能建起来,真是尴尬,代码上传的服务器上之后,不能正 ...

  9. ZooKeeper保证之单一视图(Single System Image)

    由于ZooKeeper的数据模型简单且全部在内存中,ZooKeeper的速度非常快.它提供了一系列保证(Guarantees): • 顺序一致性(Sequential Consistency) • 原 ...

  10. POJ 3233 Matrix Power Series (矩阵分块,递推)

    矩阵乘法是可以分块的,而且幂的和也是具有线性的. 不难得到 Si = Si-1+A*Ai-1,Ai = A*Ai-1.然后矩阵快速幂就可以了. /*************************** ...