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缩点+拓扑排序)
题意转化 考虑我们对于每一对激活关系建一条有向边,则对于每一个点,其答案就是其所能到达的点数. 于是,这个问题就被我们搬到了图上,成了一个图论题. 优化建图 考虑我们每次需要将一个区间向一个区间连边. ...
随机推荐
- 蓝牙baseband概述
从蓝牙specispecification中看,基带协议主要分为8个部分来介绍的,分别是概述.物理信道.物理连接.逻辑传输.逻辑连接.封包.比特流的处理.组网行为.这里面会涉及到很多的概念,主要是在概 ...
- VS2010、VS2012、VS2013、VS2015、VS2017各版本产品激活秘钥
Visual Studio 2017(VS2017) 企业版 Enterprise 注册码:NJVYC-BMHX2-G77MM-4XJMR-6Q8QF Visual Studio 2017(VS201 ...
- Linux下IP SAN共享存储操作记录
一.简单介绍SAN,即存储区域网络(storage area network and SAN protocols),它是一种高速网络实现计算机与存储系统之间的数据传输.常见的分类是FC-SAN和IP- ...
- Haproxy+Keepalived高可用环境部署梳理(主主和主从模式)
Nginx.LVS.HAProxy 是目前使用最广泛的三种负载均衡软件,本人都在多个项目中实施过,通常会结合Keepalive做健康检查,实现故障转移的高可用功能. 1)在四层(tcp)实现负载均衡的 ...
- websocket(二)——基于node js 的同步聊天应用
https://github.com/sitegui/nodejs-websocket 1.用node搭建本地服务 npm install nodejs-websocket var ws = re ...
- L2-027. 名人堂与代金券
链接:名人堂与代金券 在比赛中这题只得了2分,赛后发现原来strcmp函数并不是只返回-1,0,1三种,而是返回正数负数0 但是在我的电脑上一般就是返回前三种,只是用后面的三种更稳妥点 都怪我基础不扎 ...
- 矩形A + B HDU2524
题意 给你n*m的棋盘问有多少个矩形 分析 先看只有一行或一列的情况有1+2+....+n个,因为矩形的类型有1个最小单位格子n个,2个最小单位格子n-1个,n个最小单位格子有一个 code #inc ...
- Week2 代码复查
代码复查 http://blog.fogcreek.com/increase-defect-detection-with-our-code-review-checklist-example/ 这篇博客 ...
- Linux内核分析——第四章 进程调度
第四章 进程调度 4.1 多任务 1.多任务操作系统就是能同时并发的交互执行多个进程的操作系统. 2.多任务操作系统使多个进程处于堵塞或者睡眠状态,实际不被投入执行,这些任务尽管位于内存,但是并不处于 ...
- 20135337——linux第四次实践:字符集总结与分析
ASCII & GB2312 & UTF-8 ASCII 主要用于显示现代英语和其他西欧语言.它是现今最通用的单字节编码系统,并等同于国际标准ISO 646: 7位(bits)表示一个 ...