5017: [Snoi2017]炸弹

Time Limit: 30 Sec  Memory Limit: 512 MB
Submit: 608  Solved: 190
[Submit][Status][Discuss]

Description

在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: 
Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆。 
现在,请你帮忙计算一下,先把第 i 个炸弹引爆,将引爆多少个炸弹呢? 

Input

第一行,一个数字 N,表示炸弹个数。 
第 2∼N+1行,每行 2 个数字,表示 Xi,Ri,保证 Xi 严格递增。 
N≤500000
−10^18≤Xi≤10^18
0≤Ri≤2×10^18

Output

一个数字,表示Sigma(i*炸弹i能引爆的炸弹个数),1<=i<=N mod10^9+7。 

Sample Input

4
1 1
5 1
6 5
15 15

Sample Output

32

HINT

 

Source

 
 
显然一个点可以引爆的炸弹是一个连续的区间,对于每一个点我们向他可以引爆的最左边的炸弹到最右边的炸弹连边。可以使用线段树优化建图。
我们对建出来的图tarjan缩点,每个点维护minl和maxr。
对于这个图按拓扑序倒序dp,求出每个点的minl和maxr,统计答案即可。
 #include<iostream>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<cstdio>
#include<algorithm>
#define maxn 500005
#define ll long long
#define mod 1000000007
using namespace std;
inline ll read() {
char ch=getchar();ll x=,f=;
for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-;
for(;isdigit(ch);ch=getchar()) x=x*+ch-'';
return x*f;
}
int n,rt;
ll s[maxn*],a[maxn*],id[maxn*],tsz;
struct seg {int s[];ll mn,mx;}t[maxn*];
struct Edge {int fr,to,nxt;}e[maxn*];
int head[maxn*],sz;
void addedge(int u,int v) {e[sz].fr=u;e[sz].nxt=head[u];e[sz].to=v;head[u]=sz++;}
void build(int l,int r,int &x) {
x=++tsz;
if(l==r) {id[l]=x;t[x].mn=t[x].mx=l;return;}
int mid=l+r>>;
build(l,mid,t[x].s[]);build(mid+,r,t[x].s[]);
if(t[x].s[]) addedge(x,t[x].s[]);
if(t[x].s[]) addedge(x,t[x].s[]);
t[x].mn=l;t[x].mx=r;
return ;
}
void add(int l,int r,int x,int L,int R,int p) {
if(L<=l&&R>=r) {if(id[p]==x) return;addedge(id[p],x);return;}
int mid=l+r>>;
if(L<=mid) add(l,mid,t[x].s[],L,R,p);
if(R>mid) add(mid+,r,t[x].s[],L,R,p);
return;
}
bool inq[maxn*];
ll dfn[maxn*],low[maxn*],tim,q[maxn*],top,lm[maxn*],rm[maxn*];
int bel[maxn*],scc;
void tarjan(int x) {
dfn[x]=low[x]=++tim;q[++top]=x;inq[x]=;
for(int i=head[x];i>=;i=e[i].nxt) {
int to=e[i].to;
if(!dfn[to]){
tarjan(to);low[x]=min(low[x],low[to]);
}else if(inq[to]) low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x]) {
scc++;
lm[scc]=214748364700000000ll;
ll now;
do {
now=q[top--];inq[now]=;bel[now]=scc;
lm[scc]=min(lm[scc],t[now].mn);rm[scc]=max(rm[scc],t[now].mx);
}while(now!=x);
}
}
ll rd[maxn*];
int main() {
//freopen("bomb9.in","r",stdin);
memset(head,-,sizeof(head));
n=read();
for(int i=;i<=n;i++) {s[i]=read();a[i]=read();}
build(,n,rt);
for(int i=;i<=n;i++) {
int now=lower_bound(s+,s+n+,s[i])-s,L=lower_bound(s+,s+n+,s[i]-a[i])-s,R=upper_bound(s+,s+n+,s[i]+a[i])-s-;
if(L==R) continue;add(,n,,L,R,i);
}
for(int i=;i<=tsz;i++) if(!dfn[i]) {tarjan(i);}
int tmp=sz;sz=;memset(head,-,sizeof(head));
for(int i=;i<tmp;i++) {
int u=bel[e[i].fr],v=bel[e[i].to];
if(u==v) continue;
rd[v]++;addedge(u,v);
}
int hd=,tl=;
for(int i=;i<=scc;i++) if(!rd[i]) q[tl++]=i;
while(hd!=tl) {
int now=q[hd++];
for(int i=head[now];i>=;i=e[i].nxt) {
int to=e[i].to;rd[to]--;
if(!rd[to]) q[tl++]=to;
}
}
for(int i=scc;i>=;i--) {
int now=q[i];
for(int j=head[now];j>=;j=e[j].nxt) {
int to=e[j].to;
lm[now]=min(lm[now],lm[to]);rm[now]=max(rm[now],rm[to]);
}
}
ll ans=;
for(int i=;i<=n;i++) {
ans+=(ll)i*(rm[bel[id[i]]]-lm[bel[id[i]]]+);ans%=mod;
}
printf("%lld\n",ans);
}

[bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑的更多相关文章

  1. BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序

    BZOJ_4383_[POI2015]Pustynia_线段树优化建图+拓扑排序 Description 给定一个长度为n的正整数序列a,每个数都在1到10^9范围内,告诉你其中s个数,并给出m条信息 ...

  2. [POI2015][bzoj4383] Pustynia [线段树优化建图+拓扑排序]

    题面 bzoj权限题传送门 luogu传送门 思路 首先,这个题目显然可以从所有小的点往大的连边,然后如果没环就一定可行,从起点(入读为0)开始构造就好了 但是问题来了,如果每个都连的话,本题中边数是 ...

  3. 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)

    题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...

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

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

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

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

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

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

  7. 【2019.7.26 NOIP模拟赛 T3】化学反应(reaction)(线段树优化建图+Tarjan缩点+拓扑排序)

    题意转化 考虑我们对于每一对激活关系建一条有向边,则对于每一个点,其答案就是其所能到达的点数. 于是,这个问题就被我们搬到了图上,成了一个图论题. 优化建图 考虑我们每次需要将一个区间向一个区间连边. ...

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

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

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

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

随机推荐

  1. java-2018-01-17计划

    1.一句英语 包括单词 2.一个java版本的设计模式 参考:https://github.com/iluwatar/java-design-patterns 学习了抽象工厂模式 总结:java的RS ...

  2. could not read column value from result set:

    错误描述: INFO [http-apr-8080-exec-26] (NullableType.java:203) - could not read column value from result ...

  3. 【Python】Python 模块一考核

    1. #!/usr/bin/python  和#!/usr/bin/env python 含义 大部分python文件的头部都会写上 #!/usr/bin/python 或者 #!/usr/bin/e ...

  4. 变量可以通过into赋值

  5. 'com.alibaba.fastjson.support.spring.FastJsonpResponseBodyAdvice' is。。。。

    com.alibaba.fastjson版本1.2.43版本在通过xml方式配置spring的时候会出现这个个奇怪的问题: Class 'com.alibaba.fastjson.support.sp ...

  6. 如何用Ajax传一个数组数据

    PHP接收多个同名复选框信息不像ASP那样自动转换成为数组,这给使用带来了一定不便.但是还是有解决办法的,就是利用javascript做一下预处 理.多个同名复选框在javascript中还是以数组的 ...

  7. codeforces902C. Hashing Trees

    https://codeforces.com/contest/902/problem/C 题意: 给你树的深度和树的每个节点的深度,问你是否有重构,如果有重构输出两个不同的结构 题解: 如果相邻节点的 ...

  8. linux crontab执行shell脚本中包含相对路径的问题

    实例一 test.sh文件 echo `date`>test.log 配置crontab 设置 */1 * * * * sh /data/test.sh 在/data/目录下,未找到test.l ...

  9. oracle11g 使用数据泵导出导入数据

    终于搞定了 快写个笔记 记录下. 删除用户的时候提示已经登录了不能删除,这个需要把登录的session结束掉. select username,sid,serial# from v$session w ...

  10. Java输入输出流备忘

    重要博客: http://blog.csdn.net/hguisu/article/details/7418161 File dir = new File("\\root");   ...