[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]炸弹[线段树优化建图]的更多相关文章

  1. BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan

    Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...

  2. 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序

    题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足:  Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆.  现在 ...

  3. bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...

  4. bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)

    直接建图边数太多,用线段树优化一下 然后缩点,记下来每个点里有多少个炸弹 然后按拓扑序反向dp一下就行了 #include<bits/stdc++.h> #define pa pair&l ...

  5. 『炸弹 线段树优化建图 Tarjan』

    炸弹(SNOI2017) Description 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸 时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi ...

  6. BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]

    方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...

  7. 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流

    [BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...

  8. 【ARC069F】Flags 2-sat+线段树优化建图+二分

    Description ​ 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input ​ 第一行一个整数 N. ​ 接下来 N 行每行两个整数 xi, ...

  9. 【bzoj4699】树上的最短路(树剖+线段树优化建图)

    题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...

随机推荐

  1. dict的使用

    Python字典是可变类型数据,可以存储任意对象,如字符串,数字,元组,列表等. 字典的创键 字典有键key和值value组成,使用键值对链接:,字典也称为关联数组或哈希表. dict_person ...

  2. C#设置自定义文件图标实现双击启动

    修改注册表,双击文件直接打开 string strProject = "Exec"; string p_FileTypeName =".cdb";//文件后缀 ...

  3. mybatis入门的前期准备

    使用步骤如下: 首先创建一个Maven工程,在pom.xml文件中引入mybatis的jar包坐标 <dependencies> <dependency> <groupI ...

  4. python笔记23(面向对象课程五)

    今日内容 上节作业 单例模式 class Foo: pass obj1 = Foo() # 实例,对象 obj2 = Foo() # 实例,对象 日志模块(logging) 程序的目录结构 内容回顾 ...

  5. StarUML之九、starUML的一些特殊属性的说明

    UML的扩充性机制允许你在控制的方式下扩充UML语言. 这一类的机制包括:stereotype,标记值.约束. Stereotype扩充了UML的词汇表,允许你创建新的建筑块,这些建筑块从已有的继承而 ...

  6. float布局打破标准流,神助攻clear清浮动

    布局是什么?根据功能划分小块,再根据设计稿还原,书写静态页面,然后再在块里面填充内容,完善功能,js施加交互效果.div作为一个容器,独占一行,代码书写习惯从上至下属于标准流,而浮动float的css ...

  7. mysql删除索引

    删除索引 删除索引可以使用ALTER TABLE或DROP INDEX语句来实现.DROP INDEX可以在ALTER TABLE内部作为一条语句处理,其格式如下: drop index index_ ...

  8. linux 基础入门(9) 系统服务 systemctl 与 xinted的运用

    9.系统服务 9.1系统服务 可以把计算机理解为一个地点比如中关村大街系统服务理解为中关村大街的理发店.饭店.商场等等,每一个都是一个系统服务,为客户提供不同内容的服务 服务:常驻在内存中的程序,且可 ...

  9. MATLAB中冒号的用法解析

    MATLAB中冒号的用法解析 1.: 表示所有的意思. (1)如:a(1,:) 表示a的第1行,示例: 结果: 同样的如果a(2,:)表示a的第2行 (2)反过来,a(:,2) 表示a的第3列,示例: ...

  10. Java基础之五、Java编程思想(1-7)

    一.对象导论 1:多态的可互换对象 面向对象程序设计语言使用了后期绑定的概念. 当向对象发送消息时,被调用的代码直到运行时才能确定.也叫动态绑定. 2:单根继承结构 所有的类最终都继承自单一的基类,这 ...