[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$ 的简单路径上的点可 ...
随机推荐
- Django使用 djcelery时报ImportError: No module named south.db错误
这时候可能是安装的Django-celery.celery的版本过低引起的,可以到pycharm查看推荐的版本,把版本更换到的推荐的版本就解决了
- 记录KVM虚拟机常用操作管理命令
环境说明 centos7中的KVM NAT方式是kvm安装后的默认方式.它支持主机与虚拟机的互访,同时也支持虚拟机访问互联网,但不支持外界访问虚拟机. 检查当前的网络设置 # virsh net-li ...
- symfonos2
0x01 进入网页 啥也没有 0x02 目录爆破 啥也没有 0x03 端口扫描 知识盲区: ProFTPD 1.3.5 用ProFTPD服务权限执行复制命令,默认在'nobody'用户的特权下运行.通 ...
- HDFS基本命令fs的使用操作
HDFS(Hadoop Distributed File System)就是hadoop分布式文件系统,fs是操作HDFS文件的一个常用命令. 1.hadoop fs -help 查看fs使用帮助 2 ...
- markdown语法链接新页面打开
我们在写markdown语法的文章时,经常会写超链接,默认markdown的写法超链接打开页面都是在当前页面,对自己页面的访问不是很好,所以我们一般都希望在新页面打开.但是据我对markdwon的语法 ...
- MySQL基础(7) | 触发器
MySQL基础(7) | 触发器 基本语法 创建 CREATE TRIGGER trigger_name trigger_time trigger_event ON table_name FOR EA ...
- DNS | named.run文件很大的处理方法
在查看/var/named/data目录中发现named.run文件260G+ 总用量 267G -rw-r--r-- 1 named named 1.3K 9月 2 21:27 named.run ...
- centos的安装与配置,Linux下基本命令、权限控制,解压缩文件以及软件的安装与卸载
centos安装与网络配置 关机:shutdown -h now 重启:shutdown -r now 或 reboot linux目录结构与操作命令 使用ls命令查看目录结构 目录查看: ls [- ...
- 笔记-Git基础
git配置 git config --global user.name "xxx" //配置用户名 git config --global user.email "xxx ...
- 解决kbmMW Scheduler在任务中停止任务遇到的问题
procedure TCustomGridViewCameraDoc.InitSchedule; begin Scheduler.Schedule( procedure(const ASchedule ...