[SNOI2017]炸弹[线段树优化建图]
线段树优化建图,然后跑一边tarjan把点全部缩起来,炸一次肯定是有连锁反应的所以整个连通块都一样…于是就可以发现有些是只有单向边的不能忘记更新,没了。
#include <bits/stdc++.h>
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
#define rep(i , j , k) for(int i = j ; i <= k ; i ++)
#define Rep(i , j , k) for(int i = j ; i >= k ; i --)
using namespace std ;
using ll = long long ;
using pii = pair <int , int> ;
using vii = vector <int> ;
#define int long long
auto ot = [&]() { cerr << "ATS TXDY" << '\n' ; int ATS_nantf_txdy = true ; } ;
auto _ios = [&]() { ios :: sync_with_stdio(false) ; cin.tie(nullptr) ; cout.tie(nullptr) ; } ;
namespace stO_ATS_Orz {
template < class T > void cmax(T & x , T y) { if(x < y) x = y ; }
template < class T > void cmin(T & x , T y) { if(x > y) x = y ; }
template < class T > void abs(T x) { if(x < 0) x = -x ; }
const int N = 5e5 + 10 ;
const int mod = 1e9 + 7 ;
int n , a[N] , r[N] , id[N] ;
int minl[N << 2] , maxr[N << 2] , sccl[N << 2] , sccr[N << 2] , mx = 0 ;
vii G[N << 2] ;
void build(int l , int r , int p) {
minl[p] = l ; maxr[p] = r ; cmax(mx , p) ;
if(l == r) { id[l] = p ; return ; }
int mid = l + r >> 1 ;
build(l , mid , p << 1) ; build(mid + 1 , r , p << 1 | 1) ;
G[p].push_back(p << 1) ; G[p].push_back(p << 1 | 1) ;
}
void upd(int a , int b , int l , int r , int p , int to) {
if(a <= l && r <= b) { if(p ^ to) G[to].push_back(p) ; return ; }
int mid = l + r >> 1 ;
if(a <= mid) upd(a , b , l , mid , p << 1 , to) ;
if(b > mid) upd(a , b , mid + 1 , r , p << 1 | 1 , to) ;
}
int low[N << 2] , dfn[N << 2] , idx = 0 ;
int col[N << 2] , st[N << 2] , tp = 0 , num = 0 ;
void tarjan(int u) {
low[u] = dfn[u] = ++ idx ; st[++ tp] = u ;
for(int v : G[u]) {
if(! dfn[v]) { tarjan(v) ; cmin(low[u] , low[v]) ; }
else if(! col[v]) { cmin(low[u] , dfn[v]) ; }
}
if(low[u] == dfn[u]) {
++ num ;
do { col[st[tp]] = num ; cmin(sccl[num] , minl[st[tp]]) ; cmax(sccr[num] , maxr[st[tp]]) ; tp -- ; } while(st[tp + 1] ^ u) ;
}
}
vii reG[N << 2] ;
bool vis[N << 2] ;
void dfs(int u) {
vis[u] = 1 ;
for(int v : reG[u]) {
if(vis[v]) { cmin(sccl[u] , sccl[v]) ; cmax(sccr[u] , sccr[v]) ; }
else { dfs(v) ; cmin(sccl[u] , sccl[v]) ; cmax(sccr[u] , sccr[v]) ; }
}
}
void main() {
cin >> n ; build(1 , n , 1) ;
for(int i = 1 ; i <= n ; i ++) { cin >> a[i] >> r[i] ; }
a[n + 1] = 1e18 ; memset(sccl , 0x3f , sizeof(sccl)) ;
for(int i = 1 ; i <= n ; i ++) {
if(! r[i]) { continue ; }
int bg = lower_bound(a + 1 , a + n + 1 , a[i] - r[i]) - a ;
int ed = upper_bound(a + 1 , a + n + 1 , a[i] + r[i]) - a - 1 ;
upd(bg , ed , 1 , n , 1 , id[i]) ; minl[id[i]] = bg ; maxr[id[i]] = ed ;
}
rep(i , 1 , mx) if(! dfn[i]) tarjan(i) ;
rep(i , 1 , mx)
for(int v : G[i])
if(col[i] ^ col[v]) reG[col[i]].push_back(col[v]) ;
memset(vis , 0 , sizeof(vis)) ;
rep(i , 1 , num) if(! vis[i]) dfs(i) ;
int ans = 0 ;
rep(i , 1 , n) ans = (ans + i * (sccr[col[id[i]]] - sccl[col[id[i]]] + 1)) % mod ;
cout << ans << '\n' ;
}
}
signed main() {
_ios() ; ot() ;
return stO_ATS_Orz :: main() , 0 ;
}
[SNOI2017]炸弹[线段树优化建图]的更多相关文章
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...
- bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)
直接建图边数太多,用线段树优化一下 然后缩点,记下来每个点里有多少个炸弹 然后按拓扑序反向dp一下就行了 #include<bits/stdc++.h> #define pa pair&l ...
- 『炸弹 线段树优化建图 Tarjan』
炸弹(SNOI2017) Description 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸 时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi ...
- BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]
方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...
- 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流
[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...
- 【ARC069F】Flags 2-sat+线段树优化建图+二分
Description 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input 第一行一个整数 N. 接下来 N 行每行两个整数 xi, ...
- 【bzoj4699】树上的最短路(树剖+线段树优化建图)
题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...
随机推荐
- Webpack中hash、chunkhash和contenthash三者的区别
在webpack中有三种的方式生成哈希值,分别为hash.chunkhash和contenthash.这三种方式有着不同的用处,或者说在webpack的不同环境中,会使用不同的方式生成哈希值.那为什么 ...
- mac下搭建http服务器(apache+php),使用homebrew升级php
新版mac依旧预装了 Apache ,但是已经不能在 「系统偏好设置」中的「Web 共享」来开启了,需要手动通过命令行开启. 启动Apache 启动:sudo apachectl start 停止:s ...
- Java中HashSet的重复性与判等运算重载
目录 还有一个故事--(平行世界篇) 还有一个美丽的梦幻家园:java.util 并且还有一个善战的达拉崩巴:HashSet 还有另外一个故事(不是虚假传说) 还有一对涂满毒药的夺命双匕:equals ...
- jmeter脚本调试过程
1.添加监听器:查看结果树,再回放脚本 2.权限验证,例如:cookies a.谷歌浏览器F12获取session
- #《H.264和MPEG-4视频压缩》# 二. 图像质量
为了规范.评价.比较不同的视频通信系统,我们需要建立评价图像质量的准则.视觉效果的测量非常困难,而且并不精确,因为影响结果的因素众多.图像质量的认定是一个主观化的东西,许多影响它的因素都难以给出完整而 ...
- 【转】JS 的 new 到底是干什么的?
原文:https://zhuanlan.zhihu.com/p/23987456?refer=study-fe 大部分讲 new 的文章会从面向对象的思路讲起,但是我始终认为,在解释一个事物的时候,不 ...
- gcc 与g++
which gcc 查看gcc 主要针对 .c which g++ 查看g++ 主要针对 .cpp yum install gcc 安装gc ...
- Python 静态类型检查 mypy 示例
以下所有例子都参考了最新版本的 Python 文档与 mypy 文档 必备条件 安装最新版本的 Python 和 mypy 要学会按需配置自己的编辑器,比如我的 VSCode 就装好了 Python ...
- css3神奇的圆角边框、阴影框及其图片边框
css3圆角,建议IE10以上 如果border-radius 单位是百分比,则参考为自身宽高,因此当宽高不一致时,圆角为不规则形状 如果border-radius 为50%,则为椭圆:当宽高一致时, ...
- mysql第五课
修改表中一行或多行数据: SELECT*FROM student;+----+------+------+| id | name | ban |+----+------+------+| 1 | ...