这道题我做了有半个月了...终于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. 阶段3 2.Spring_08.面向切面编程 AOP_10 总结和作业安排

    由转账添加事物,使得我们的操作变的非常麻烦.重复代码产生了很多 实际的开发中如果想记录日志每个方法都要执行 如果判断用户是否登陆也是每个方法都需要判断 这些重复的代码我们都需要去解决. 解决的方式,以 ...

  2. HttpRunnerManager(一)--安装

    1.相关地址 (1)中文文档介绍:https://cn.httprunner.org/ (2)相关安装包下载地址:链接:https://pan.baidu.com/s/13SP1mFsNKrLK0sn ...

  3. 微信小程序---设备信息

    1.学习大纲: 2.获取系统信息: wx.getSystemInfo({ success: function(res) { // success console.log(res) } }) } 3.获 ...

  4. [Python3] 027 常用模块 time

    目录 time 1. 时间戳 2. UTC 时间 3. 夏令时 4. 时间元组 5. 举例 5.1 例子1 例子2 例子3 例子4 例子5 例子6 例子7 time 1. 时间戳 一个时间表示,根据不 ...

  5. 修改python pip3镜像源

    方法一: pip3 install 包名  -i 镜像源url 主要的镜像源: pip3 install tornado -i https://pypi.douban.com/simple/  pip ...

  6. QT use of undeclared identifier 'cout'

    在QT 5.12中直接使用cout将提示错误如下: 添加库 #include<iostream>,并将cout&end改为std::cout&std::endl 代码如下: ...

  7. 洛谷 P1879 玉米田Corn Fields 题解

    题面 一道思维难度不大的状态压缩,也并不卡常,但细节处理要格外注意: f[i][j]表示前i行最后一行状态是j的方案数 #include <bits/stdc++.h> #define p ...

  8. Makefile中include、-include、sinclude

    include.-include.sinclude使用 在 Makefile 使用 include 关键字可以把别的 Makefile 包含进来,这很像 C 语言的#include,被包含的文件会原模 ...

  9. Packet flow in l2(receive and transmit)

    Receive 1.  napi && none napi 讲网络收报过程,必然要涉及到网卡收报模型发展历史.总体上看,网络收报过经历了如下发展过程: 轮询 ---à 中断 ---à ...

  10. Java获取文件的后缀名。

    /** * 详细步骤 */ private static void test1() { //获取文件的原始名称 String originalFilename = "tim.g (1).jp ...