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. docker/qemu中是如何对设备管理的

    文件系统中包括实际的磁盘中可读可写的. 容器中看到的设备是啥子呢?--docker qemu也是一样,在qemu中添加一个设备的物理意义是啥子嘛 其实设备也没啥好新奇的,不就是一个普通的文件么,然后在 ...

  2. java 自定义序列化

    pom.xml 导包 创建自己的序列化类,继承 com.fasterxml.jackson.databind.JsonSerializer<T> 抽象类 重写 serialize() 方法 ...

  3. Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D

    D. Bear and Two Paths time limit per test 2 seconds memory limit per test 256 megabytes input standa ...

  4. [lucene系列笔记2]在eclipse里初步使用lucene的索引和查询功能

    首先,new一个java project,名字叫做LuceneTools. 然后,在project里new一个class,名字叫做IndexFiles.这个类用来给文件建索引(建好索引以后就可以高效检 ...

  5. Linux Top 命令参数解析

    转载自:http://www.jb51.net/LINUXjishu/34604.html TOP是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户 ...

  6. (转)如何用python抓取网页并提取数据

    最近一直在学这部分,今日发现一篇好文,虽然不详细,但是轮廓是出来了: 来自crifan:http://www.crifan.com/crawl_website_html_and_extract_inf ...

  7. 复选框 checkbox 选中事件

    项目中用的jquery-1.11 今天需要检测一个checkbox的选中状态,想当然的用 .attr("checked") ,结果发现,无论是否选中,这个值都是 undefined ...

  8. jzoj2700 【GDKOI2012模拟02.01】数字

    传送门:https://jzoj.net/senior/#main/show/2700 [题目大意] 令n为正整数,S(n)为n的各位数字之和,令

  9. HIT 1917 2—SAT

    题目大意:一国有n个党派,每个党派在议会中都有2个代表, 现要组建和平委员会,要从每个党派在议会的代表中选出1人,一共n人组成和平委员会. 已知有一些代表之间存在仇恨,也就是说他们不能同时被选为和平委 ...

  10. [bzoj4516][Sdoi2016]生成魔咒——后缀自动机

    Brief Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示.例如可以将魔咒字符 1.2 拼凑起来形成一个魔咒串 [1,2]. 一个魔咒串 S 的非空字串被称为魔咒串 S 的生 ...