bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)
直接建图边数太多,用线段树优化一下
然后缩点,记下来每个点里有多少个炸弹
然后按拓扑序反向dp一下就行了
#include<bits/stdc++.h>
#define pa pair<ll,int>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=5e5+,maxp=maxn*,maxl=maxn*,P=1e9+;
const ll inf=1e18+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} int N;
ll pos[maxn],r[maxn];
int rg[maxn][],id[maxn],ch[maxp][],pct,root;
int eg[maxl][],egh[maxp],ect;
int eg2[maxl][],egh2[maxp],ect2,ine[maxp];
int dfn[maxp],low[maxp],tot,stk[maxp],sh;
int bel[maxp],nct,hav[maxp],hh[maxp];
int val[maxp],rk[maxp];
bool instk[maxp],islef[maxp],to[maxp];
queue<int> q; inline void adeg(int a,int b){
eg[++ect][]=b;eg[ect][]=egh[a];egh[a]=ect;
}
inline void adeg2(int a,int b){
ine[b]++;
eg2[++ect2][]=b;eg2[ect2][]=egh2[a];egh2[a]=ect2;
} void build(int &p,int l,int r){
p=++pct;
if(l==r) id[l]=p,islef[p]=;
if(l<r){
int m=l+r>>;
build(ch[p][],l,m);
build(ch[p][],m+,r);
adeg(p,ch[p][]),adeg(p,ch[p][]);
}
} void conn(int p,int l,int r,int x,int y,int z){
if(x>y) return;
if(x<=l&&r<=y){
adeg(z,p);
}else{
int m=l+r>>;
if(x<=m) conn(ch[p][],l,m,x,y,z);
if(y>=m+) conn(ch[p][],m+,r,x,y,z);
}
} void tarjan(int x){
dfn[x]=low[x]=++tot;
stk[++sh]=x;instk[x]=;
for(int i=egh[x];i;i=eg[i][]){
int b=eg[i][];
if(instk[b]) low[x]=min(low[x],dfn[b]);
else if(!dfn[b]){
tarjan(b);
low[x]=min(low[x],low[b]);
}
}
if(dfn[x]==low[x]){
++nct;
while(sh){
bel[stk[sh]]=nct;
hav[stk[sh]]=hh[nct],hh[nct]=stk[sh];
val[nct]+=islef[stk[sh]];
instk[stk[sh]]=;
sh--;
if(stk[sh+]==x) break;
}
}
} int main(){
//freopen(".in","r",stdin);
int i,j,k;
N=rd();
for(i=;i<=N;i++) pos[i]=rd(),r[i]=rd();
for(i=;i<=N;i++){
rg[i][]=lower_bound(pos+,pos+N+,pos[i]-r[i])-pos;
rg[i][]=upper_bound(pos+,pos+N+,pos[i]+r[i])-pos-;
// printf("%d %d %d\n",i,rg[i][0],rg[i][1]);
}
build(root,,N);
for(i=;i<=N;i++){
conn(root,,N,rg[i][],i-,id[i]);
conn(root,,N,i+,rg[i][],id[i]);
}
for(i=;i<=pct;i++){
if(!dfn[i]) tarjan(i);
}
for(i=;i<=nct;i++){
for(j=hh[i];j;j=hav[j]){
for(k=egh[j];k;k=eg[k][]){
int bb=bel[eg[k][]];if(bb==i) continue;
if(!to[bb]) adeg2(i,bb),to[bb]=;
}
} for(j=hh[i];j;j=hav[j]){
for(k=egh[j];k;k=eg[k][]){
int bb=bel[eg[k][]];
to[bb]=;
}
}
}
int nn=;
for(i=;i<=nct;i++){
if(!ine[i]) q.push(i);
}
while(!q.empty()){
int p=q.front();q.pop();
rk[++nn]=p;
for(i=egh2[p];i;i=eg2[i][]){
int b=eg2[i][];
if(--ine[b]==) q.push(b);
} }
for(i=nct;i;i--){
int p=rk[i];
for(j=egh2[p];j;j=eg2[j][]){
int b=eg2[j][];
val[p]+=val[b];
}
}
ll ans=;
for(i=;i<=N;i++){
ans=(ans+1ll*i*val[bel[id[i]]])%P;
}
printf("%lld\n",ans);
return ;
}
bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)的更多相关文章
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
- bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...
- BZOJ5017 炸弹(线段树优化建图+Tarjan+拓扑)
Description 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被 ...
- 『炸弹 线段树优化建图 Tarjan』
炸弹(SNOI2017) Description 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸 时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi ...
- Libre OJ 2255 (线段树优化建图+Tarjan缩点+DP)
题面 传送门 分析 主体思路:若x能引爆y,从x向y连一条有向边,最后的答案就是从x出发能够到达的点的个数 首先我们发现一个炸弹可以波及到的范围一定是坐标轴上的一段连续区间 我们可以用二分查找求出炸弹 ...
- 模拟赛T2 线段树优化建图+tarjan+拓扑排序
然而这只是 70pts 的部分分,考场上没想到满分怎么做(现在也不会) code: #include <cstdio> #include <string> #include & ...
- 炸弹:线段树优化建边+tarjan缩点+建反边+跑拓扑
这道题我做了有半个月了...终于A了... 有图为证 一句话题解:二分LR线段树优化建边+tarjan缩点+建反边+跑拓扑统计答案 首先我们根据题意,判断出来要炸弹可以连着炸,就是这个炸弹能炸到的可以 ...
- 【2019.7.26 NOIP模拟赛 T3】化学反应(reaction)(线段树优化建图+Tarjan缩点+拓扑排序)
题意转化 考虑我们对于每一对激活关系建一条有向边,则对于每一个点,其答案就是其所能到达的点数. 于是,这个问题就被我们搬到了图上,成了一个图论题. 优化建图 考虑我们每次需要将一个区间向一个区间连边. ...
随机推荐
- Nginx URL后面不加斜杠301重定向
今天开发碰到一个问题,其实之前就有这个问题,但是一直都没去关注,今天测试碰到了就解决一下. 问题情况: 当我请求 http://admindev.jingruiauto.com/store/views ...
- 微信小程序:java后台获取openId
一.功能描述 openId是某个微信账户对应某个小程序或者公众号的唯一标识,但openId必须经过后台解密才能获取(之前实现过前台解密,可是由于微信小程序的种种限制,前台解密无法在小程序发布后使用) ...
- 宇宙最强IDE,查看设计器报错,看不了设计界面
在使用自定义控件或者用户控件的时候,查看设计器打不开界面的原因: Loaded事件中加以下判断条件:if (!DesignerProperties.GetIsInDesignMode(this))
- linux下rsync和tar增量备份梳理
前面总结过一篇全量备份/增量备份/差异备份说明,下面介绍下linux下rsync和tar两种增量备份的操作记录: 1)rsync备份 rsync由于本身的特性,在第一次rsync备份后,以后每次都只是 ...
- 如何利用Android Studio打包React Native APK
ok!百度出来的东西很杂,所以,这里介绍一种最简单,最合适我们(新手,应该是吧)的APK的打包方式! 当然!这种打包是基于Android Studio的,所以,注意喽!!!! 废话不多说开始吧! 首先 ...
- article元素以及section
<p>发表日期:<time pubdate="pubdate">2015/10/30</time></p> article元素有自己 ...
- 构建之法--初识Git
该作业来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE1/homework/2103 GitHub地址:https://github.com/GVic ...
- ACL访问控制
/etc/squid/squid.conf 定义语法: acl aclname acltype string acl aclname acltype "file" s ...
- JsTree使用一例
SearchDesignPatent.treeContainer().jstree({ 'core' : { 'data' : json.data }, }).bind('click.jstree', ...
- live-server
live-server的安装与使用 初始化npm:npm init 安装live-server:cnpm install -g live-server 根目录启动live-server:live-se ...