BZOJ5017 Snoi2017炸弹(线段树+强连通分量+缩点+传递闭包)
容易想到每个炸弹向其能引爆的炸弹连边,tarjan缩点后bitset传递闭包。进一步发现每个炸弹能直接引爆的炸弹是一段连续区间,于是线段树优化建图即可让边的数量降至O(nlogn)。再冷静一下由于能间接引爆的炸弹也是一段连续区间,传递闭包时只要记录可达点的左右端点即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 500010
#define M N<<2
#define ll long long
#define P 1000000007
ll read()
{
ll x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,p[M],dfn[M],low[M],stk[M],Set[M],L[M],R[M],root,t,cnt,top,tot,ans=;
bool flag[M];
ll a[N],b[N];
struct data{int to,nxt;
}edge[M<<];
struct data2{int l,r;
}tree[M];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void build(int &k,int l,int r)
{
if (l==r) {k=l;return;}
k=++cnt;
int mid=l+r>>;
build(tree[k].l,l,mid);
build(tree[k].r,mid+,r);
addedge(k,tree[k].l),addedge(k,tree[k].r);
}
void add(int k,int l,int r,int x,int y,int p)
{
if (l==x&&r==y) {addedge(p,k);return;}
int mid=l+r>>;
if (y<=mid) add(tree[k].l,l,mid,x,y,p);
else if (x>mid) add(tree[k].r,mid+,r,x,y,p);
else add(tree[k].l,l,mid,x,mid,p),add(tree[k].r,mid+,r,mid+,y,p);
}
void tarjan(int k)
{
dfn[k]=low[k]=++cnt;stk[++top]=k;flag[k]=;
for (int i=p[k];i;i=edge[i].nxt)
if (!dfn[edge[i].to]) tarjan(edge[i].to),low[k]=min(low[k],low[edge[i].to]);
else if (flag[edge[i].to]) low[k]=min(low[k],dfn[edge[i].to]);
if (dfn[k]==low[k])
{
tot++;L[tot]=n+,R[tot]=;
while (stk[top]!=k)
{
Set[stk[top]]=tot;
if (stk[top]<=n) L[tot]=min(L[tot],stk[top]),R[tot]=max(R[tot],stk[top]);
flag[stk[top]]=;
top--;
}
Set[k]=tot;if (k<=n) L[tot]=min(L[tot],k),R[tot]=max(R[tot],k);flag[k]=,top--;
}
}
namespace newgraph
{
int p[M]={},degree[M]={},q[M],t=;
struct data{int to,nxt;}edge[M<<];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;degree[y]++;}
void topsort()
{
int head=,tail=;
for (int i=;i<=tot;i++) if (!degree[i]) q[++tail]=i;
while (tail<tot)
{
int x=q[++head];
for (int i=p[x];i;i=edge[i].nxt)
{
degree[edge[i].to]--;
if (!degree[edge[i].to]) q[++tail]=edge[i].to;
}
}
}
void dp()
{
for (int i=tot;i>=;i--)
{
int x=q[i];
for (int j=p[x];j;j=edge[j].nxt)
L[x]=min(L[x],L[edge[j].to]),R[x]=max(R[x],R[edge[j].to]);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj5017.in","r",stdin);
freopen("bzoj5017.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read();
for (int i=;i<=n;i++) a[i]=read(),b[i]=read();
cnt=n;
build(root,,n);
for (int i=;i<=n;i++)
{
int x,y;
int l=,r=i;
while (l<=r)
{
int mid=l+r>>;
if (a[i]-b[i]<=a[mid]) x=mid,r=mid-;
else l=mid+;
}
l=i,r=n;
while (l<=r)
{
int mid=l+r>>;
if (a[i]+b[i]>=a[mid]) y=mid,l=mid+;
else r=mid-;
}
add(root,,n,x,y,i);
}
t=cnt;cnt=;
for (int i=;i<=t;i++) if (!dfn[i]) tarjan(i);
for (int k=;k<=t;k++)
for (int i=p[k];i;i=edge[i].nxt)
if (Set[k]!=Set[edge[i].to]) newgraph::addedge(Set[k],Set[edge[i].to]);
newgraph::topsort();
newgraph::dp();
for (int i=;i<=n;i++) ans=(ans+1ll*i*(R[Set[i]]-L[Set[i]]+))%P;
cout<<ans;
return ;
}
BZOJ5017 Snoi2017炸弹(线段树+强连通分量+缩点+传递闭包)的更多相关文章
- BZOJ5017 [Snoi2017]炸弹[线段树优化建边+scc缩点+DAG上DP/线性递推]
方法一: 朴素思路:果断建图,每次二分出一个区间然后要向这个区间每个点连有向边,然后一个环的话是可以互相引爆的,缩点之后就是一个DAG,求每个点出发有多少可达点. 然后注意两个问题: 上述建边显然$n ...
- bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
- [SNOI2017]炸弹[线段树优化建图]
[SNOI2017]炸弹 线段树优化建图,然后跑一边tarjan把点全部缩起来,炸一次肯定是有连锁反应的所以整个连通块都一样-于是就可以发现有些是只有单向边的不能忘记更新,没了. #include & ...
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点
loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点 链接 loj 思路 用交错关系建出图来,发现可以直接缩点,拓扑统计. 完了吗,不,瓶颈在于边数太多了,线段树优化建图. 细节 ...
- bzoj5017: [Snoi2017]炸弹
Description 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被 ...
- HDU 3639 Hawk-and-Chicken(强连通分量+缩点)
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013480600/article/details/32140501 HDU 3639 Hawk-a ...
- POJ1236Network of Schools[强连通分量|缩点]
Network of Schools Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 16571 Accepted: 65 ...
随机推荐
- wpf- DataGrid 常用属性和事件
组件所在命名空间: System.Windows.Controls 组件常用方法: BeginEdit:使DataGrid进入编辑状态. CancelEdit:取消DataGrid的编辑状态. Col ...
- CF 1064 D. Labyrinth
D. Labyrinth http://codeforces.com/contest/1064/problem/D 题意: n*m的矩阵,只能往左走l次,往右走r次,上下走无限制,问能走到多少个点. ...
- SRM First Problem && SRM 638 250pts NamingConvention
NamingConvention 题意: 给一个字符串,删掉所有的'_',然后将‘_'后的第一个字符改成大写. 代码: #include<bits/stdc++.h> using name ...
- 10_SpringBoot集成TkMybatis插件
10_SpringBoot集成TkMybatis插件 明天你好向前奔跑 关注 0.5 2018.09.11 11:15 字数 163 阅读 3794评论 0喜欢 3 @Author Jacky Wa ...
- centOS上安装最新git 2.4.0
git 地址: https://www.kernel.org/pub/software/scm/git/ 1. 先安装一堆依赖 yum install curl curl-devel zlib-de ...
- 解决 idea template jsp模板中使用自定义路径 模板不显示问题
${} 是一个模板中的关键字,所以建立时需要用 \ 注释即可正常显示 ${APP_PATH}
- 使用SCSS扩展Bootstrap4
摘要 因为打算写一个小网站,而个人时间又不是那么充裕,所以没有选择前后端分离的架构. 对于非前后端分离应用来说,Bootstrap应该是目前的最佳前端框架之一了. 而Bootstrap4,是Boots ...
- textbox的验证
代码如下: textBox1.KeyDown += (a, b) => { if (b.KeyCode == Keys.Enter) { textBox2.Focus(); } }; textB ...
- Linux TCP/IP调优参数 /proc/sys/net/目录
所有的TCP/IP调优参数都位于/proc/sys/net/目录. 例如, 下面是最重要的一些调优参数,后面是它们的含义: /proc/sys/net/core/rmem_default " ...
- Python接口测试实战4(上) - 接口测试框架实战
如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战 ...