Description
Input
Output
题解
因为每一个炸弹爆炸后引爆的是一个区间的炸弹,所以想到线段树优化建图。
然后可能有环所以跑Tarjan求强连通分量。最后拓扑合并答案。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
const int N=;
const int mod=1e9+;
queue<int> q;
int cnt,cnt1,head[N*],head1[N*];
int num,id[N*],di[N*];
int dfn[N*],low[N*],tot1,top,stack[N*],book[N*],num1,col[N*],tmp;
long long a[N],r[N],b[N],maxx[N*],minn[N*];
int n,tot,in[N*];
long long ans;
struct tree{
int l,r;
}tr[N*];
struct edge{
int to,nxt,u;
}e[N*],e1[N*];
void add(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].u=u;
e[cnt].to=v;
head[u]=cnt;
}
void add1(int u,int v){
cnt1++;
e1[cnt1].nxt=head1[u];
e1[cnt1].to=v;
head1[u]=cnt1;
}
void build(int l,int r,int now){
num=max(num,now);
tr[now].l=l;tr[now].r=r;
if(r==l){
id[l]=now;
di[now]=l;
return;
}
int mid=(tr[now].l+tr[now].r)>>;
build(l,mid,now*);
build(mid+,r,now*+);
add(now,now*);
add(now,now*+);
}
void update(int l,int r,int now,int u){
if(tr[now].l==l&&tr[now].r==r){
add(u,now);
return;
}
int mid=(tr[now].l+tr[now].r)>>;
if(l>mid)update(l,r,now*+,u);
else if(r<=mid)update(l,r,now*,u);
else{
update(l,mid,now*,u);
update(mid+,r,now*+,u);
}
}
void Tarjan(int u){
dfn[u]=low[u]=++tot1;
stack[++top]=u;
book[u]=;
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(dfn[v]==){
Tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(book[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
int x;
num1++;
minn[num1]=4e18;
maxx[num1]=-4e18;
bool flag=false;
do{
x=stack[top--];
book[x]=;
col[x]=num1;
if(di[x]){
if(!flag){
minn[num1]=a[di[x]]-r[di[x]];
maxx[num1]=a[di[x]]+r[di[x]];
flag=true;
}
else{
minn[num1]=min(minn[num1],a[di[x]]-r[di[x]]);
maxx[num1]=max(maxx[num1],a[di[x]]+r[di[x]]);
}
}
}while(x!=u);
}
}
int lower(long long x){
int ll=;int rr=tot+;
while(ll<=rr){
int mid=(ll+rr)>>;
if(b[mid]>=x){
tmp=mid;
rr=mid-;
}
else ll=mid+;
}
return tmp;
}
int uppr(long long x){
int ll=;int rr=tot+;
while(ll<=rr){
int mid=(ll+rr)>>;
if(b[mid]>x){
tmp=mid;
rr=mid-;
}
else ll=mid+;
}
return tmp;
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%lld%lld",&a[i],&r[i]);
b[i]=a[i];
}
tot=unique(b+,b++n)-(b+);
b[tot+]=4e18;
build(,n,);
for(int i=;i<=n;i++){
int x=lower(a[i]-r[i]);
int y=uppr(a[i]+r[i])-;
update(x,y,,id[i]);
}
for(int i=;i<=num;i++){
if(!dfn[i])Tarjan(i);
}
for(int i=;i<=cnt;i++){
if(col[e[i].u]==col[e[i].to])continue;
add1(col[e[i].to],col[e[i].u]);
in[col[e[i].u]]++;
}
for(int i=;i<=num1;i++){
if(in[i]==)q.push(i);
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head1[u];i;i=e1[i].nxt){
int v=e1[i].to;
in[v]--;
if(in[v]==)q.push(v);
minn[v]=min(minn[v],minn[u]);
maxx[v]=max(maxx[v],maxx[u]);
}
}
for(int i=;i<=n;i++){
int x=uppr(maxx[col[id[i]]])-;
int y=lower(minn[col[id[i]]]);
ans+=(long long)((long long)(x-y+)*(long long)i)%mod;
ans%=mod;
}
printf("%lld",ans);
return ;
}
BZOJ5017 炸弹(线段树优化建图+Tarjan+拓扑)的更多相关文章
-
bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)
直接建图边数太多,用线段树优化一下 然后缩点,记下来每个点里有多少个炸弹 然后按拓扑序反向dp一下就行了 #include<bits/stdc++.h> #define pa pair&l ...
-
【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 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...
-
『炸弹 线段树优化建图 Tarjan』
炸弹(SNOI2017) Description 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸 时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi ...
-
模拟赛T2 线段树优化建图+tarjan+拓扑排序
然而这只是 70pts 的部分分,考场上没想到满分怎么做(现在也不会) code: #include <cstdio> #include <string> #include & ...
-
炸弹:线段树优化建边+tarjan缩点+建反边+跑拓扑
这道题我做了有半个月了...终于A了... 有图为证 一句话题解:二分LR线段树优化建边+tarjan缩点+建反边+跑拓扑统计答案 首先我们根据题意,判断出来要炸弹可以连着炸,就是这个炸弹能炸到的可以 ...
-
【2019.7.26 NOIP模拟赛 T3】化学反应(reaction)(线段树优化建图+Tarjan缩点+拓扑排序)
题意转化 考虑我们对于每一对激活关系建一条有向边,则对于每一个点,其答案就是其所能到达的点数. 于是,这个问题就被我们搬到了图上,成了一个图论题. 优化建图 考虑我们每次需要将一个区间向一个区间连边. ...
-
[SNOI2017]炸弹[线段树优化建图]
[SNOI2017]炸弹 线段树优化建图,然后跑一边tarjan把点全部缩起来,炸一次肯定是有连锁反应的所以整个连通块都一样-于是就可以发现有些是只有单向边的不能忘记更新,没了. #include & ...
随机推荐
-
Git 常用命令详解
Git 是一个很强大的分布式版本管理工具,它不但适用于管理大型开源软件的源代码(如:linux kernel),管理私人的文档和源代码也有很多优势(如:wsi-lgame-pro) Git 的更多介绍 ...
-
python生成RSS(PyRSS2Gen)
既然能够用python解析rss,那么也顺带研究下生成rss. 其实很简单,只是生成一个比较特殊点的xml文档而已. 这里我使用了PyRss2Gen,用法很简单,看代码就知道了,如下: import ...
-
textView截取字符串-医生工作台1期
textfield截取字符串 ios7 会崩溃 解: 之前的写法是这样的 正确的写法: 先判断markedTextRange是否为nil, markedTextRange这个属性是啥意思呢 表 ...
-
Ioc容器Autofac系列(2)-- asp.net mvc中整合autofac
经过上篇蜻蜓点水的介绍后,本篇通过实例快速上手autofac,展示当asp.net mvc引入了autofac之后会带来什么. 创建Asp.net MVC并引入Autofac 首先,创建一个MVC站点 ...
-
使用原生js与jQuery分别实现一个简单的tab页签
tab页签通常适用于空间有限而内容较多同时兼顾页面美观度不给用户一种信息过量视觉疲劳的情形.使用面非常广,下面我们用两种方法简单实现之. 首先,构建页面元素.页签的可点击部分我们通常用列表来承载,包括 ...
-
Jenkins构建Android项目持续集成之单元测试及代码覆盖率
单元测试 在软件开发中一直在推崇TDD(测试驱动开发),但是一直不能被有效的执行或者并不是真正的测试驱动开发(先开发后写单元测试),因为我们懒!而Android开发又是大多应用层面的开发,很多都是和视 ...
-
Web项目、Http协议简介
Web 静态web项目 静态web项目就是一个文件夹.静态Web项目 就是文件夹中都是静态资源. 如何将web项目部署到tomcat? 将web项目的文件夹复制到webapps目录下.比如把test文 ...
-
PHP命令注入笔记
一.PHP命令注入介绍 在学习php相关的攻击时,遇到了Command Injection,即命令注入攻击,是指这样一种攻击手段,黑客通过把HTML代码输入一个输入机制(例如缺乏有效验证限制的表格域) ...
-
【php】phpExcel使用教程,如何导出excel表格
[1]下载phpExcel类文件 可在官方去下载 我们只需要classes中的文件,把Classes文件复制到项目中 只需要2个文件就可以了 一个就是phpExcel(刚才我们复制过来的文件 Cla ...
-
QT下 enum转QString
先在QT5.7 class EnumTest :public QObject { Q_OBJECT public: EnumTest(); enum PINYINENUM { XYDA, XYDB, ...