https://www.lydsy.com/JudgeOnline/problem.php?id=5017

暴力:

对于每一个炸弹,枚举所有的炸弹,看它爆炸能不能引爆那个炸弹

如果能,由这个炸弹向引爆的炸弹连单向边

tarjan所点后拓扑排序

在拓扑图上倒着统计答案

可以得到一个炸弹能引爆的编号最小mi和最大的炸弹mx,mx-mi+1就是先引爆这个炸弹一共能引爆的炸弹数

优化:

一个炸弹一定是向一段区间连边

所以用线段树优化,这样向一个区间连边就变成了向一个点连边

注意存边的空间一定要开的足够大

还有tarjan缩完点后不一定是一棵树,因为是有向图缩点

#include<cstdio>
#include<vector>
#include<iostream>
#include<algorithm> using namespace std; const int mod=1e9+; #define N 500001 typedef long long LL; int n; int id[N*],num;
int front[N*],to[N*],nxt[N*],from[N*],tot; LL pos[N],rad[N]; int dfn[N*],low[N*],tim;
int st[N*],top;
bool vis[N*]; int cnt;
int bl[N*],mi[N*],mx[N*]; vector<int>V[N*];
int in[N*]; int q[N*]; template<typename T>
void read(T &x)
{
x=; int f=; char c=getchar();
while(!isdigit(c)) { if(c=='-') f=-; c=getchar(); }
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
x*=f;
} void add(int u,int v)
{
to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u;
//printf("%d %d\n",u,v);
} /*void add2(int u,int v)
{
to2[++tot2]=v; nxt2[tot2]=front2[u]; front2[u]=tot2;
}*/ void build(int k,int l,int r)
{
id[k]=++num;
if(l==r)
{
add(id[k],l);
return;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
add(id[k],id[k<<]);
add(id[k],id[k<<|]);
} void burst(int k,int l,int r,int opl,int opr,int who)
{
if(l>=opl && r<=opr)
{
add(who,id[k]);
return;
}
int mid=l+r>>;
if(opl<=mid) burst(k<<,l,mid,opl,opr,who);
if(opr>mid) burst(k<<|,mid+,r,opl,opr,who);
} void init()
{
read(n);
num=n;
build(,,n);
for(int i=;i<=n;++i) read(pos[i]),read(rad[i]);
for(int i=;i<=n;++i) burst(,,n,lower_bound(pos+,pos+n+,pos[i]-rad[i])-pos,upper_bound(pos+,pos+n+,pos[i]+rad[i])-pos-,i);
} void tarjan(int x)
{
dfn[x]=low[x]=++tim;
st[++top]=x;
vis[x]=true;
for(int i=front[x];i;i=nxt[i])
if(!dfn[to[i]])
{
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(vis[to[i]]) low[x]=min(low[x],dfn[to[i]]);
int y;
if(low[x]==dfn[x])
{
cnt++;
mi[cnt]=n+;
mx[cnt]=;
while(x!=y)
{
y=st[top--];
vis[y]=false;
bl[y]=cnt;
if(y<=n)
{
mi[cnt]=min(mi[cnt],y);
mx[cnt]=max(mx[cnt],y);
}
}
}
} void rebuild()
{
for(int i=;i<=tot;++i)
if(bl[from[i]]!=bl[to[i]])
{
//add2(bl[from[i]],bl[to[i]]);
V[bl[from[i]]].push_back(bl[to[i]]);
in[bl[to[i]]]++;
}
} void topsort()
{
int head=,tail=;
for(int i=;i<=cnt;++i)
if(!in[i]) q[tail++]=i;
int now,siz,t;
while(head<tail)
{
now=q[head++];
siz=V[now].size();
for(int i=;i<siz;++i)
{
t=V[now][i];
in[t]--;
if(!in[t]) q[tail++]=t;
}
}
for(int i=tail-;i;--i)
{
now=q[i];
siz=V[now].size();
for(int i=;i<siz;++i)
{
t=V[now][i];
mi[now]=min(mi[now],mi[t]);
mx[now]=max(mx[now],mx[t]);
}
}
} void work()
{
// printf("%d %d\n",num,tot);
for(int i=;i<=num;++i)
if(!dfn[i]) tarjan(i);
rebuild();
topsort();
int ans=;
for(int i=;i<=n;++i)
{
ans+=1LL*i*(mx[bl[i]]-mi[bl[i]]+)%mod;
ans-=ans>=mod ? mod : ;
}
printf("%d",ans);
} int main()
{
init();
work();
}

bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)的更多相关文章

  1. BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan

    Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...

  2. bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...

  3. BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]

    方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...

  4. [SNOI2017]炸弹[线段树优化建图]

    [SNOI2017]炸弹 线段树优化建图,然后跑一边tarjan把点全部缩起来,炸一次肯定是有连锁反应的所以整个连通块都一样-于是就可以发现有些是只有单向边的不能忘记更新,没了. #include & ...

  5. 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序

    题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足:  Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆.  现在 ...

  6. bzoj5017 炸弹 (线段树优化建图+tarjan+拓扑序dp)

    直接建图边数太多,用线段树优化一下 然后缩点,记下来每个点里有多少个炸弹 然后按拓扑序反向dp一下就行了 #include<bits/stdc++.h> #define pa pair&l ...

  7. 炸弹:线段树优化建边+tarjan缩点+建反边+跑拓扑

    这道题我做了有半个月了...终于A了... 有图为证 一句话题解:二分LR线段树优化建边+tarjan缩点+建反边+跑拓扑统计答案 首先我们根据题意,判断出来要炸弹可以连着炸,就是这个炸弹能炸到的可以 ...

  8. bzoj千题计划196:bzoj4826: [Hnoi2017]影魔

    http://www.lydsy.com/JudgeOnline/problem.php?id=4826 吐槽一下bzoj这道题的排版是真丑... 我还是粘洛谷的题面吧... 提供p1的攻击力:i,j ...

  9. bzoj千题计划300:bzoj4823: [Cqoi2017]老C的方块

    http://www.lydsy.com/JudgeOnline/problem.php?id=4823 讨厌的形状就是四联通图 且左右各连一个方块 那么破坏所有满足条件的四联通就好了 按上图方式染色 ...

随机推荐

  1. 直接使用security.basic.path无效|——springboot2.0以上的security的配置

    问题 springcloud 版本 为 Finchley.RELEASEspringboot 版本为 2.0.3.RELEASE 现在有需求,/swagger-ui.html 页面需要添加登录认证,但 ...

  2. 安装PHP 类库PEAR

    PHP扩展与应用库常识 当php项目里没有pear时: 单独安装解决方案 下载下面连接的文件至go-pear.phar.http://pear.php.net/go-pear.phar该文件最好放到P ...

  3. 环境变量PS1,修改命令行提示符样式

    推荐模板  export PS1="\[\e[37;40m\][\[\e[31;40m\]\u\[\e[0m@\[\e[33;40m\]\H \[\e[36;40m\]\w\[\e[0m\] ...

  4. H5左侧滑删除简单实现

    简单的左滑删除 实现功能 在一个列表的一条中,往左滑动时,右边出现删除按钮,点击可删除这一条 实现办法 列表中一项为父div,其中包含内容div和删除按钮span 父div相对定位,设置宽度.内容di ...

  5. 使用item pipeline处理保存数据

    一个Item Pipeline 不需要继承特定基类,只需要实现某些特定方法,面向接口. class MyPipeline(object): def __init__(self): "&quo ...

  6. A/D和D/A的学习

    从我们学到的知识了解到,我们的单片机是一个典型的数字系统.数字系统只能对输入的数字信号进行处理,其输出信号也是数字信号.但是在工业检测系统和日常生活中的许多物理量都是模拟量,比如温度.长度.压力.速度 ...

  7. java == 与 equals

    1.基本数据类型用"==" java的基本数据类型,也称为原始的数据类型.它们分别是: byte, short, char, int, long, float, double, b ...

  8. A1132. Cut Integer

    Cutting an integer means to cut a K digits lone integer Z into two integers of (K/2) digits long int ...

  9. crond守护进程实现定时监控某进程占有内存的大小

    1)添加计划任务 crontab -e会使用某个编辑器打开某个文件,然后在内输入需要执行的计划任务,保存后在/var/spool/cron/crontabs/下会出现以用户名命名的文件 2)计划任务如 ...

  10. java web整合office web apps

    1.下载安装vmware虚拟机 2.下载windows server 2012或者window server 2012 R2的iso镜像 http://www.xp85.com/html/Window ...