容易想到每个炸弹向其能引爆的炸弹连边,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炸弹(线段树+强连通分量+缩点+传递闭包)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点

    loj#2255. 「SNOI2017」炸弹 线段树优化建图,拓扑,缩点 链接 loj 思路 用交错关系建出图来,发现可以直接缩点,拓扑统计. 完了吗,不,瓶颈在于边数太多了,线段树优化建图. 细节 ...

  7. bzoj5017: [Snoi2017]炸弹

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

  8. HDU 3639 Hawk-and-Chicken(强连通分量+缩点)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u013480600/article/details/32140501 HDU 3639 Hawk-a ...

  9. POJ1236Network of Schools[强连通分量|缩点]

    Network of Schools Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 16571   Accepted: 65 ...

随机推荐

  1. Web前端优化常用规则

    一,尽量减少HTTP请求 二,使用CDN(内容分发网络) 三,添加Expire/Cache-Control头 四,启用Gzip压缩 五,将CSS放在层叠样式表放到head里面 六,将Script放到页 ...

  2. day6 网络 HTML模板

    1.HTML模板 HTML模板 baidu一下 http://www.cssmoban.com/ http://www.cnblogs.com/web-d/archive/2010/04/16/171 ...

  3. CF 1083 A. The Fair Nut and the Best Path

    A. The Fair Nut and the Best Path https://codeforces.com/contest/1083/problem/A 题意: 在一棵树内找一条路径,使得从起点 ...

  4. mysql 错误代码 1248

    1248 - Every derived table must have its own alias (MYSQL错误) 这句话的意思是说每个派生出来的表都必须有一个自己的别名,给派生表加上一个别名就 ...

  5. Karma与TSLint

    TSLint TSLint是一个可扩展的静态分析工具,用于检查TypeScript代码的可读性,可维护性和功能性错误.收到现代编辑和构建系统的广泛支持,并且可以使用您自己的路由,配置和格式化. 安装 ...

  6. C# VS,连接到oracle 报要升级到8.多少版本的错

    1:确定服务器的oracle版本 2:本地的客户端版本要和服务器一致 3:操作系统位数要一致

  7. Python中print函数中中逗号和加号的区别

    strip()方法,去除字符串开头或者结尾的空格 s = " a b c " new_s = s.strip() print("-------->%s<--- ...

  8. php缩放处理png和jpg图片

    本例子介绍使用php自带的GD库对png和jpg图片进行放大和缩小处理 <?php$target_width = 120; //目标图片宽度 $target_height = 150; //目标 ...

  9. JMeter学习笔记(二) 一些实际应用的基础操作

    我在CSDN上面找到一位大师整理的jmeter性能测试基础,分享到这里继续学习 https://blog.csdn.net/u011541946/article/category/6893578/1

  10. 导出Office365中的组及成员

    Set-ExecutionPolicy unrestricted $cred = Get-Credential  $session = New-PSSession -ConfigurationName ...