这道题我做了有半个月了...终于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. apache用户认证

    创建一个目录abc:mkdir abc在此目录下建一个文件:12.txt正常情况下可以访问. 建立用户认证,从而使用户访问特定目录文件需要认证 在虚拟主机配置文件中即vim /usr/local/ap ...

  2. mysql 各数据类型的大小及长度

    数字型 类型 大小 范围(有符号) 范围(无符号) 用途 TINYINT 1 字节 (-128,127) (0,255) 小整数值 SMALLINT 2 字节 (-32 768,32 767) (0, ...

  3. MariaDB select

    1.环境部署: syntax语法错误 查询基本使用(条件,排序,聚合函数,分组,分页) --创建学生表 create table students ( id int unsigned not null ...

  4. 从git上pull下的代码,执行时提示:ModuleNotFoundError: No module named '......',解决方法如下:

    方法一: 如果没有安装,如下: 1.PyCharm : file-> setting->Project interpreter–>package2.右侧有个+ 点击3.进入后 搜索p ...

  5. LeetCode.941-有效山形数组(Valid Mountain Array)

    这是悦乐书的第360次更新,第387篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第222题(顺位题号是941).给定一个整数数组A,当且仅当它是一个有效的山形数组时返回 ...

  6. 如何理解springcloud微服务项目中,eureka,provider,consumer它们之间的关系?

    eureka负责注册provider和consumer的服务信息 provider负责与数据库进行交互,实现数据持久化,并给consumer提供服务 consumer与前端交互,通过与Eureka同源 ...

  7. python 并发编程 socket 服务端 客户端 阻塞io行为

    阻塞io行为 server.accept server.recv client.send recv,accept  分为两个阶段 1.wait for data 对方把数据经过网络延迟送到自己的操作系 ...

  8. GTS原理、架构

    全局事务服务(Global Transaction Service,简称 GTS)是阿里新推出的分布式事务处理方案. 1. GTS 的目标 GTS是一个面向互联网交易场景的分布式事务解决方案. 制约分 ...

  9. equals与== 和toString方法

    /** * equals()方法的使用 * * 1.java.lang.Object类中的equals()方法的定义: * * public boolean equals(Object obj) { ...

  10. Ubuntu下Win10虚拟机卡顿问题解决

    问题描述 Ubuntu下用VMware创建了一个Windows10的虚拟机,初始给的配置如下: Memory: 4GB Graphics Memory: 1GB Hard Disk: 60GB 用的时 ...