这道题我做了有半个月了...终于A了...

有图为证

一句话题解:二分LR线段树优化建边+tarjan缩点+建反边+跑拓扑统计答案

首先我们根据题意,判断出来要炸弹可以连着炸,就是这个炸弹能炸到的可以是由它能炸到的其他炸弹来炸到.也就是说具有拓扑性.(a->b,b->c==a->c)

所以我们首先有了一个想法:建反图,tarjan缩点,跑拓扑.

为什么建反图?因为i能炸到j,所以j能炸到的i就可以炸到了,所以建反图从j->i可以实现这一点.

但是每个炸弹能炸到的是一个区间,怎么搞呢?

线段树优化建边,每次log次建边.

 //二分LR线段树优化建边+tarjan缩点+建反边+跑拓扑统计答案
#include<bits/stdc++.h>
#define N 500005
#define INF 0x3f3f3f3f
#define p 1000000007
#define LL long long
#define lch k<<1
#define rch k<<1|1
#define xx puts("xuefnngh");
using namespace std;
int n,num_bian,num_stack,num_dfn,num_tarjan;
int ls[N<<],rs[N<<],tree[N],mx[N<<],mi[N<<],head[N<<],fm[N*],to[N*],nxt[N*];
int dfn[N<<],low[N<<],sta[N<<],in_sta[N<<],Mi[N<<],Mx[N<<],bel[N<<],in_deg[N<<];
LL dis[N],R[N];
void add(int x,int y){if(x==y)return;/*printf("%d %d\n",x,y);*/to[++num_bian]=y;fm[num_bian]=x;nxt[num_bian]=head[x];head[x]=num_bian;}
void Build(int k,int l,int r){
ls[k]=l;rs[k]=r;mi[k]=INF;
if(l==r)return (void) (tree[l]=k);
Build(lch,l,(l+r)/);Build(rch,(l+r)/+,r);
add(lch,k);add(rch,k);
}
void find(int k,int g,int L,int R){
if(ls[k]==rs[k])return (void)(mx[k]=R,mi[k]=L);
if(g<=rs[lch])find(lch,g,L,R);else find(rch,g,L,R);
mx[k]=max(mx[lch],mx[rch]);mi[k]=min(mi[lch],mi[rch]);
}
void connect(int k,int l,int r,int g){
if(ls[k]>=l&&rs[k]<=r) return (void) (add(k,g));
if(l<=rs[lch])connect(lch,l,r,g);
if(r>=ls[rch])connect(rch,l,r,g);
}
void tarjan(int x){
dfn[x]=low[x]=++num_dfn;in_sta[x]=;sta[++num_stack]=x;
for(int i=head[x];i;i=nxt[i])
if(!dfn[to[i]])
tarjan(to[i]),low[x]=min(low[x],low[to[i]]);
else if(in_sta[to[i]])low[x]=min(low[x],dfn[to[i]]);
if(dfn[x]==low[x]){
int z;++num_tarjan;Mi[num_tarjan]=INF;
/*printf("huan:%d\n",num_tarjan);*/
do{
z=sta[num_stack--];
/*printf("%d ",z);*/
bel[z]=num_tarjan;
in_sta[z]=;
Mi[num_tarjan]=min(Mi[num_tarjan],mi[z]);
Mx[num_tarjan]=max(Mx[num_tarjan],mx[z]);
}while(z!=x);
/*puts("");
printf("%d %d\n",Mi[num_tarjan],Mx[num_tarjan]);*/
}
}
int que[N<<];
void top_sort(){
for(int i=;i<=num_tarjan;++i)if(!in_deg[i])que[++que[]]=i;
for(int i=;i<=que[];++i)
for(int j=head[que[i]];j;j=nxt[j]){
--in_deg[to[j]];
Mx[to[j]]=max(Mx[to[j]],Mx[que[i]]);Mi[to[j]]=min(Mi[to[j]],Mi[que[i]]);
if(!in_deg[to[j]])que[++que[]]=to[j];
}
}
int main(){
scanf("%d",&n);Build(,,n);
for(int i=;i<=n;++i)scanf("%lld%lld",&dis[i],&R[i]);
for(int i=;i<=n;++i){
int L=lower_bound(dis+,dis+n+,dis[i]-R[i])-dis;
int RR=upper_bound(dis+,dis+n+,dis[i]+R[i])-dis-;
/*printf("%d %d %d\n",i,L,RR);*/
connect(,L,RR,tree[i]);find(,i,L,RR);/*printf("333%d\n",tree[i]);*/
}
for(int i=;i<=tree[n];++i)if(!dfn[i])tarjan(i);
/*puts("xuueue");*/
int num_pre=num_bian;num_bian=;memset(head,,sizeof head);
for(int i=;i<=num_pre;++i)if(bel[fm[i]]!=bel[to[i]])add(bel[fm[i]],bel[to[i]]),in_deg[bel[to[i]]]++;
top_sort();
LL Ans=;for(int i=;i<=n;++i)(Ans+=(1ll*Mx[bel[tree[i]]]-Mi[bel[tree[i]]]+)*i%p+p)%=p/*,printf("%lld\n",Ans)*/;printf("%lld",Ans);
}

炸弹:线段树优化建边+tarjan缩点+建反边+跑拓扑的更多相关文章

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

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

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

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

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

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

  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. [SNOI2017]炸弹[线段树优化建图]

    [SNOI2017]炸弹 线段树优化建图,然后跑一边tarjan把点全部缩起来,炸一次肯定是有连锁反应的所以整个连通块都一样-于是就可以发现有些是只有单向边的不能忘记更新,没了. #include & ...

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

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

  8. [bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑

    5017: [Snoi2017]炸弹 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 608  Solved: 190[Submit][Status][ ...

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

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

随机推荐

  1. web开发(四) 一次性验证码的代码实现

    在网上看见一篇不错的文章,写的详细. 以下内容引用那篇博文.转载于<http://www.cnblogs.com/whgk/p/6426072.html>,在此仅供学习参考之用. 其实实现 ...

  2. Selenium 2自动化测试实战17(警告框处理)

    一.警告框处理 在WebDriver中处理JavaScript所生成的alert.confirm以及prompt十分简单,只需要使用switch_to_alert()方法定位到alert/confir ...

  3. Java学习之==>数组【array】

    一.定义数组 /** * 一维数组定义 * * 为数组插入元素 */ public void case1() { // 声明 int[] arr1; // 声明+初始化 int[] arr2 = ne ...

  4. vue中html、css、js 分离

    在正常的创建和引用vue文件都是html.css.js三者在一起的,这样写起来虽然方便了,但是页面比较大或者代码比较多的情况下,即使使用组件有时代码也比较多,简单来说查找不变不利于编程,大的来说影像优 ...

  5. 【图形学手记】Inverse Transform Sampling 逆转换抽样

    需求: 我们通过调查,得知大多数人在20岁左右初恋,以20岁为基准,以随机变量X表示早于或晚于该时间的年数,为了简单,假设X值域为[-5,5],并且PDF(X)是一个正态分布函数(当然可以为任意分布, ...

  6. Spring容器启动源码分析

    1. 前言 最近搭建的工程都是基于SpringBoot,简化配置的感觉真爽.但有个以前的项目还是用SpringMvc写的,看到满满的配置xml文件,却有一种想去深入了解的冲动.折腾了好几天,决心去写这 ...

  7. Tutorial : Implementing Django Formsets

    A step-by-step tutorial for setting up and testing a standard Django formset. I’ve noticed on #djang ...

  8. poj3252(数位dp)(模板)

    题目链接:https://vjudge.net/problem/POJ-3252 题意:求[l,r]之间的Round Number数,RN数即化为二进制后0的个数不少于1的个数的数. 思路:之前用组合 ...

  9. [转帖]Ubuntu忘记超级用户root密码,重新设置密码

    Ubuntu忘记超级用户root密码,重新设置密码 版权声明:本文为博主原创文章,转载必须指明出处. https://blog.csdn.net/weixin_37909391/article/det ...

  10. CentOS7之SVN服务配置

    操作系统:CentOS Linux release 7.2.1511 (Core)    Subversion软件版本:subversion-1.7.14-10.el7.x86_64 1.首先检查sv ...