[LOJ#2255][BZOJ5017][Snoi2017]炸弹
[LOJ#2255][BZOJ5017][Snoi2017]炸弹
试题描述
输入
输出
一个数字,表示Sigma(i*炸弹i能引爆的炸弹个数),1<=i<=N mod10^9+7。
输入示例
输出示例
数据规模及约定
见“输入”
题解
显然一个炸弹能引爆的范围一定是一段连续的区间,于是我们就考虑求它的左右端点。
考虑一种容易漏掉的情况:一个炸弹 a 引爆左边一个炸弹 b,b 引爆 a 右侧的 c,c 引爆 b 左侧的 d……这种情况我们不难发现从 a 到 d,炸弹的爆炸半径一定倍增(比如若 b 的半径小于 a 半径的两倍,由于 b 可以引爆 a 右边的 c,所以 a 可以直接引爆 c,不需要借助 b)。
剩下的情况就是连锁爆炸(即爆炸只往一个方向传递),处理这个东西我们只需要用单调栈正反扫一遍处理出每个炸弹向左向右连锁爆炸能炸到的最远的炸弹就可以了(不妨设向左向右最远的炸弹编号分别为 lft[i] 和 rgt[i])。
最后我们用 RMQ 维护一下 lft[i] 的最小值,rgt[i] 的最大值;若要求炸弹 i 的范围,就是不停扩张的过程,最多扩张 log(n) 次。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define LL long long const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
LL read() {
LL x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 500010
#define maxlog 19
#define MOD 1000000007 int n, q[maxn], top, lft[maxn], rgt[maxn];
LL X[maxn], R[maxn]; int Log[maxn], mn[maxlog][maxn], mx[maxlog][maxn];
void init() {
for(int i = 1; i <= n; i++) mn[0][i] = lft[i], mx[0][i] = rgt[i];
for(int j = 1; (1 << j) <= n; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
mn[j][i] = min(mn[j-1][i], mn[j-1][i+(1<<j-1)]),
mx[j][i] = max(mx[j-1][i], mx[j-1][i+(1<<j-1)]);
return ;
}
int _l, _r;
void query(int ql, int qr) {
int t = Log[qr-ql+1];
_l = min(mn[t][ql], mn[t][qr-(1<<t)+1]);
_r = max(mx[t][ql], mx[t][qr-(1<<t)+1]);
return ;
} int main() {
n = read();
for(int i = 1; i <= n; i++) X[i] = read(), R[i] = read(); Log[1] = 0;
for(int i = 2; i <= n; i++) Log[i] = Log[i>>1] + 1; lft[1] = 1;
q[top = 1] = 1;
for(int i = 2; i <= n; i++) {
int l = 1, r = top;
while(l < r) {
int mid = l + r >> 1;
if(X[q[mid]] < X[i] - R[i]) l = mid + 1; else r = mid;
}
if(X[q[l]] < X[i] - R[i]) lft[i] = i;
else lft[i] = lft[q[l]];
while(top && lft[i] <= lft[q[top]]) top--;
q[++top] = i;
}
rgt[n] = n;
q[top = 1] = n;
for(int i = n - 1; i; i--) {
int l = 1, r = top;
while(l < r) {
int mid = l + r >> 1;
if(X[q[mid]] > X[i] + R[i]) l = mid + 1; else r = mid;
}
// printf("%d: %d | %d %lld\n", i, l, q[l], X[q[l]]);
if(X[q[l]] > X[i] + R[i]) rgt[i] = i;
else rgt[i] = rgt[q[l]];
while(top && rgt[i] >= rgt[q[top]]) top--;
q[++top] = i;
}
// for(int i = 1; i <= n; i++) printf("LR [%d %d]\n", lft[i], rgt[i]);
init();
int ans = 0;
for(int i = 1; i <= n; i++) {
int l = lft[i], r = rgt[i];
_l = n + 1; _r = 0;
for(;;) {
query(l, r);
if(l == _l && r == _r) break;
l = _l; r = _r;
}
ans += ((LL)i * (r - l + 1)) % MOD;
if(ans >= MOD) ans -= MOD;
// printf("[%d, %d]\n", l, r);
} printf("%d\n", ans); return 0;
}
[LOJ#2255][BZOJ5017][Snoi2017]炸弹的更多相关文章
- loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点
loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点 链接 loj 思路 用交错关系建出图来,发现可以直接缩点,拓扑统计. 完了吗,不,瓶颈在于边数太多了,线段树优化建图. 细节 ...
- loj #2255. 「SNOI2017」炸弹
#2255. 「SNOI2017」炸弹 题目描述 在一条直线上有 NNN 个炸弹,每个炸弹的坐标是 XiX_iXi,爆炸半径是 RiR_iRi,当一个炸弹爆炸时,如果另一个炸弹所在位置 X ...
- [bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑
5017: [Snoi2017]炸弹 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 608 Solved: 190[Submit][Status][ ...
- BZOJ5017 Snoi2017炸弹(线段树+强连通分量+缩点+传递闭包)
容易想到每个炸弹向其能引爆的炸弹连边,tarjan缩点后bitset传递闭包.进一步发现每个炸弹能直接引爆的炸弹是一段连续区间,于是线段树优化建图即可让边的数量降至O(nlogn).再冷静一下由于能间 ...
- BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]
方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...
- bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)
https://www.lydsy.com/JudgeOnline/problem.php?id=5017 暴力: 对于每一个炸弹,枚举所有的炸弹,看它爆炸能不能引爆那个炸弹 如果能,由这个炸弹向引爆 ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
- bzoj5017: [Snoi2017]炸弹
Description 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被 ...
- bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...
随机推荐
- 【转】iOS学习笔记(十五)——数据库操作(SQLite)
SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库.SQLite最初的设计目标是用于嵌入式系统,它占用资源非常少,在嵌入式设备中,只需要几百K的 ...
- jQuery工作中遇到的几个插件
图片上传插件:uploadify 表单验证插件:formValidator
- 厌食?暴食?试试这个 VR 新疗法
今日导读 “我知道我要吃饭,但我真的什么都吃不下.” “我脑子里想的只有吃东西,吃吃吃!” ....... 作为一个正常人,我们完全无法想象患厌食症或贪食症人群所受的痛苦.长期的厌食,会使一个人瘦的只 ...
- 《队长说得队》【Alpha】Scrum meeting 4
项目 内容 这个作业属于哪个课程 >>2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 >>实验十二 团队作业8:软件测试与ALPHA冲刺 团队名称 ...
- 题解 P1379 【八数码难题】
传送门 用STL中的queue,map,string写了个广搜,用一个string保存状态(见代码)注:STL比较慢,可以做一些优化(或者开O2) #include<iostream> # ...
- pandas中层次化索引与切片
Pandas层次化索引 1. 创建多层索引 隐式索引: 常见的方式是给dataframe构造函数的index参数传递两个或是多个数组 Series也可以创建多层索引 Series多层索引 B =Ser ...
- 【Git版本控制】git将单个文件回退到某一版本
暂定此文件为a.jsp 1.进入到a.jsp所在目录,通过 git log a.jsp查看a.jsp的更改记录 2.找到想要回退的版本号:例如 fcd2093 通过 git reset fcd2 ...
- spring boot自动配置实现
自从用了spring boot,都忘记spring mvc中的xml配置是个什么东西了,再也回不去.为啥spring boot这么好用呢, 约定大于配置的设计初衷, 让我们只知道维护好applicat ...
- Voyager的路由
修改默认的后台登录路由 打开web.php,把prefix值改为你想设置的值,如back: Route::group(['prefix' => 'back'], function () { Vo ...
- ubuntu安装easygui模块
使用pip安装easygui 如果未安装pip,则使用如下命令 sudo apt-get install python-pip 安装完pip后,使用如下命令安装easygui sudo pip ins ...