P5025 [SNOI2017] 炸弹 题解
题意
link.
题解
我们充分发扬人类智慧。
考虑到可能连锁爆炸,我们不能通过一个单纯的二分来解决问题。
考虑
记
我们以
对于每一个
但是可以连锁爆炸,所以我们需要选出一个
此时就可以转移了:
但找出
考虑开一棵线段树,维护
因为满足
此时只需要查询一下区间
然后你就会发现它错了(貌似样例都过不了)。
我们不能把思维固定在
有可能我们先爆炸炸到
所以要反着再转移一次。
然后你就会发现它又错了(貌似会错第二个点)。
因为我们通过走右边到达了左边,此时我们还需要再走一次左边,因为走过来不一定是最小的(真烦)。
右边同理。
然后你就会发现似乎可以无穷无尽地走下去了……
不管怎么说先重复几边上文的过程吧。
但值得庆幸的是,重复两遍就能过了,因为此时已经把所有方案考虑完了(或者是数据水了点)。
时间复杂度:
如果你们想的话,可以把二分放到外面预处理,省掉了一点点
namespace zqh {
const int N = 5e5 + 5;
int n;
struct bomb { // 炸弹结构体
int x, r;
} a[N];
int dpl[N], dpr[N];
struct segment { // 线段
int mx, mx_id; // 最大值,最大值编号,下同
int mn, mn_id;
};
struct segment_tree { // 线段树
#define ls (id << 1)
#define rs (id << 1 | 1)
segment seg[N << 2];
void pushup(int id) {
if (seg[ls].mn < seg[rs].mn) {
seg[id].mn = seg[ls].mn;
seg[id].mn_id = seg[ls].mn_id;
} else {
seg[id].mn = seg[rs].mn;
seg[id].mn_id = seg[rs].mn_id;
}
if (seg[ls].mx > seg[rs].mx) {
seg[id].mx = seg[ls].mx;
seg[id].mx_id = seg[ls].mx_id;
} else {
seg[id].mx = seg[rs].mx;
seg[id].mx_id = seg[rs].mx_id;
}
}
void build(int id, int lft, int rht) { // 建树
seg[id].mn = LLONG_MAX;
seg[id].mx = LLONG_MIN;
if (lft == rht) {
seg[id].mn_id = seg[id].mx_id = lft;
seg[id].mn = a[lft].x - a[lft].r;
seg[id].mx = a[lft].x + a[lft].r;
return;
}
int mid = (lft + rht) / 2;
build(ls, lft, mid);
build(rs, mid + 1, rht);
pushup(id);
}
segment query(int id, int lft, int rht, int l, int r) {
if (rht < l || r < lft)
return {LLONG_MIN, -1, LLONG_MAX, -1};
if (l <= lft && rht <= r)
return seg[id];
int mid = (lft + rht) / 2;
segment t1 = query(ls, lft, mid, l, r),
t2 = query(rs, mid + 1, rht, l, r), ret;
if (t1.mn < t2.mn) {
ret.mn = t1.mn;
ret.mn_id = t1.mn_id;
} else {
ret.mn = t2.mn;
ret.mn_id = t2.mn_id;
}
if (t1.mx > t2.mx) {
ret.mx = t1.mx;
ret.mx_id = t1.mx_id;
} else {
ret.mx = t2.mx;
ret.mx_id = t2.mx_id;
}
return ret;
}
} st;
void dp() { // 跑一次 dp
for (int i = 2; i <= n; i++) { // 算 f(直接走左边)
int l = 1, r = i - 1, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (abs(a[mid].x - a[i].x) <= a[i].r) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
if (ans == -1)
continue;
segment t = st.query(1, 1, n, ans, i - 1);
dpl[i] = min(dpl[i],
min((dpl[t.mn_id] == -1 ? LLONG_MAX : dpl[t.mn_id]), ans));
}
for (int i = n - 1; i >= 1; i--) { // 算 g(直接走右边)
int l = i + 1, r = n, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (abs(a[mid].x - a[i].x) <= a[i].r) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
if (ans == -1)
continue;
segment t = st.query(1, 1, n, i + 1, ans);
dpr[i] = max(dpr[i],
max((dpr[t.mx_id] == -1 ? LLONG_MIN : dpr[t.mx_id]), ans));
}
for (int i = 2; i <= n; i++) { // 算 g(走左边再走右边)
int l = 1, r = i - 1, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (abs(a[mid].x - a[i].x) <= a[i].r) {
ans = mid;
r = mid - 1;
} else {
l = mid + 1;
}
}
if (ans == -1)
continue;
segment t = st.query(1, 1, n, ans, i - 1);
dpr[i] = max(dpr[i],
max((dpr[t.mx_id] == -1 ? LLONG_MIN : dpr[t.mx_id]), ans));
}
for (int i = n - 1; i >= 1; i--) { // 算 f(走右边再走左边)
int l = i + 1, r = n, ans = -1;
while (l <= r) {
int mid = (l + r) / 2;
if (abs(a[mid].x - a[i].x) <= a[i].r) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
if (ans == -1)
continue;
segment t = st.query(1, 1, n, i + 1, ans);
dpl[i] = min(dpl[i],
min((dpl[t.mn_id] == -1 ? LLONG_MAX : dpl[t.mn_id]), ans));
}
}
void init() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].x >> a[i].r;
dpl[i] = dpr[i] = i;
}
}
void solve() {
st.build(1, 1, n); // 建树
dp(); // 跑两次
dp();
int ans = 0;
for (int i = 1; i <= n; i++) { // 统计答案
// cout << dpl[i] << " " << dpr[i] << endl;
if (dpl[i] == -1 && dpr[i] == -1) {
ans = 1LL * (ans + 1 * i) % mod;
continue;
}
if (dpl[i] == -1) {
ans = (ans + 1LL * (1LL * (dpr[i] - i + 1) % mod * i) % mod) % mod;
continue;
}
if (dpr[i] == -1) {
ans = (ans + 1LL * (1LL * (i - dpl[i] + 1) % mod * i) % mod) % mod;
continue;
}
ans = (ans + 1LL * (1LL * (dpr[i] - dpl[i] + 1) % mod * i) % mod) % mod;
}
cout << ans;
}
void main() {
init();
solve();
}
} // namespace zqh
这样速度快得飞起,在
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库