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. mysql Navicat 连接MySQL 8.0.11 出现2059错误

    https://www.cnblogs.com/lifan1998/p/9177731.html 原因 mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8 ...

  2. 【cf849ABC】

    849A - Odds and Ends 问能否将序列划分为奇数个长度奇数的奇数开头奇数结尾的子区间. 一开始想dp..不过没必要. const int N=201000; int n,a[N]; i ...

  3. 【HDU - 4340】Capturing a country(树形DP)

    BUPT2017 wintertraining(15) #8A 题意 n(<100)个城市组成的树.A攻击i城市需要a[i]代价,B需要b[i].如果一个城市的邻居被A攻击了,那么A攻击它只要A ...

  4. P3723 [AH2017/HNOI2017]礼物

    题目链接:[AH2017/HNOI2017]礼物 题意: 两个环x, y 长度都为n k可取 0 ~ n - 1      c可取任意值 求 ∑ ( x[i] - y[(i + k) % n + 1] ...

  5. 脚本自动封掉并发数过高的 IP

    防止扫描器对服务器恶意扫描,可以对 iptables 规则做了比较严格的配置. 以下配置可作为参考: #lo -A INPUT -i lo -j ACCEPT -A OUTPUT -o lo -j A ...

  6. Hdoj 1789 Doing Homework again 题解

    Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of h ...

  7. Nginx优化文件编写

    server_tokens off; #并不会让nginx执行的速度更快,关闭它可隐藏错误页面中的nginx版本号charset utf-8,gbk; #字符#sendfile on;#tcp_nop ...

  8. github上的面试库

    https://yuchengkai.cn/docs/zh/frontend/#%E5%86%85%E7%BD%AE%E7%B1%BB%E5%9E%8B https://github.com/taiz ...

  9. ZOJ 4062 Plants vs. Zombies(二分答案)

    题目链接:Plants vs. Zombies 题意:从1到n每个位置一棵植物,植物每浇水一次,增加ai高度.人的初始位置为0,人每次能往左或往右走一步,走到哪个位置就浇水一次.求m步走完后最低高度的 ...

  10. luogu5020 [NOIp2018]货币系统 (完全背包)

    我那个新的货币系统,就是把原来的货币系统中能被其他数表示的数删掉 那我就算有多少数能被别的数表示,那肯定是要被比它小的表示 于是排个序做完全背包就好了 但是我太zz不会完全背包,然后写了个bitset ...