CodeForces 781E Andryusha and Nervous Barriers 线段树 扫描线
题意:
有一个h×wh×w的矩形,其中有nn个水平的障碍。从上往下扔一个小球,遇到障碍后会分裂成两个,分别从障碍的两边继续往下落。
如果从太高的地方落下来,障碍会消失。
问从每一列的上方扔一个小球,最终落到下面有多少个球。
分析:
每一个障碍对应一个矩形,也就是它的有效范围,在这个范围内下落的球才会落到上面,否则障碍会消失。
维护一条从下往上的扫描线,用线段树维护[1,w][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;
}
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 继承的思维:从思维模式到架构设计的深度解析
· 如何在 .NET 中 使用 ANTLR4
· 后端思维之高并发处理方案
· 理解Rust引用及其生命周期标识(下)
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· 35岁程序员的中年求职记:四次碰壁后的深度反思
· 当职场成战场:降职、阴谋与一场硬碰硬的抗争
· ShadowSql之.net sql拼写神器
· Excel百万数据如何快速导入?
· 无需WebView,Vue也能开发跨平台桌面应用
2016-03-15 POJ 2104 K-th Number 主席树
2015-03-15 LA 3135 (优先队列) Argus
2015-03-15 UVa 11991 Easy Problem from Rujia Liu?
2015-03-15 UVa 11995 I Can Guess the Data Structure!
2015-03-15 LA 3485 (积分 辛普森自适应法) Bridge