bzoj 5017 [Snoi2017]炸弹
题面
https://www.lydsy.com/JudgeOnline/problem.php?id=5017
题解
如果数据范围小一点那么就缩点 然后跑一个基础的DAG上的dp就好了
但是边数是$O(n^2)$的 所以就会炸
然后发现题目的特殊性
每一个点连向的点是连续的 换言之就是每个点和一个连续的段连上了一条边
那么我们把段拆开 用类似线段树的做法拆成log个小段 然后把这个点与这些小段连边即可
记得把每个段向它的儿子连上边
这样点数和边数都是$O(n \log n)$ 就可以了
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll; ll read(){
ll x=,f=;char c=getchar();
while(c<'' || c>''){if(c=='-')f=-;c=getchar();}
while(c>='' && c<=''){x=x*+c-'';c=getchar();}
return x*f;
} const int mod=1e9+;
const int maxn=;
int n,nwn;
ll pos[maxn],rad[maxn];
struct Node{
int l,r;
} tr[maxn*]; int dy[maxn]; inline bool pd(int a,int b){
return abs(pos[a]-pos[b])<=rad[a];
} int head[maxn*],nxt[maxn*],to[maxn*],cnt;
int rhead[maxn*],rnxt[maxn*],rto[maxn*],rcnt; inline void add_edge(int a,int b){
to[++cnt]=b;
nxt[cnt]=head[a];
head[a]=cnt;
rto[++rcnt]=a;
rnxt[rcnt]=rhead[b];
rhead[b]=rcnt;
} void build(int i,int l,int r){
tr[i].l=l,tr[i].r=r;
nwn=max(nwn,i);
if(l==r){
dy[l]=i;return;
}
int md=(l+r)>>;
build(i*,l,md);
build(i*+,md+,r);
add_edge(i,i*);
add_edge(i,i*+);
} inline void work(int ind,int i,int l,int r){
if(tr[i].l>r || tr[i].r<l) return;
if(tr[i].l>=l && tr[i].r<=r){
add_edge(dy[ind],i);
return;
}
work(ind,i*,l,r);
work(ind,i*+,l,r);
} int vis[maxn*];
int seq[maxn*],tot;
int col; void dfs1(int nw){
vis[nw]=;
for(int i=rhead[nw];i;i=rnxt[i]){
int v=rto[i];
if(vis[v]) continue;
dfs1(v);
}
seq[++tot]=nw;
} void dfs2(int nw){
vis[nw]=col;
for(int i=head[nw];i;i=nxt[i]){
int v=to[i];
if(vis[v]) continue;
dfs2(v);
}
} int sz[maxn*];
int ans[maxn*];
bool vis2[maxn*]; void dfs3(int nw){
if(ans[vis[nw]]==) ans[vis[nw]]=sz[vis[nw]];
vis2[nw]=;
for(int i=head[nw];i;i=nxt[i]){
int v=to[i];
if(vis2[v]) continue;
dfs3(v);
if(vis[v]!=vis[nw])
ans[vis[nw]]+=ans[vis[v]];
}
} int main(){
#ifdef LZT
freopen("in","r",stdin);
#endif
n=read();
build(,,n);
for(int i=;i<=n;i++)
pos[i]=read(),rad[i]=read();
int l,r;
for(int i=;i<=n;i++){
int L=,R=i;
while(L<=R){
int md=(L+R)>>;
if(pos[i]-pos[md]>rad[i]) L=md+;
else R=md-,l=md;
}
L=i,R=n;
while(L<=R){
int md=(L+R)>>;
if(pos[md]-pos[i]>rad[i]) R=md-;
else L=md+,r=md;
}
work(i,,l,r);
} for(int i=;i<=nwn;i++){
if(tr[i].l==) continue;
if(!vis[i]) dfs1(i);
}
memset(vis,,sizeof(vis)); for(int i=tot;i>=;i--)
if(!vis[seq[i]]) ++col,dfs2(seq[i]); for(int i=;i<=nwn;i++) if(tr[i].l && tr[i].l==tr[i].r) sz[vis[i]]++;
dfs3(); ll res=;
for(int i=;i<=nwn;i++){
if(tr[i].l<tr[i].r) continue;
res+=tr[i].l*1ll*ans[vis[i]]%mod;
res%=mod;
}
printf("%lld\n",res); return ;
} /*
4
1 1
5 1
6 5
15 15
*/
Review
动机?
首先缩点+dp是显然的
然后我就没有想到怎么优化
其实也不难想啊 就是要把连续的一段点转化成几个点 也就是区间->几个点 那么就上线段树嘛
然后写的时候注意总点数的处理
按照我的线段树写法 一棵树中 最小编号到最大编号之间不连续 也就是有一些编号不对应任何点
这样在遍历所有点的时候要判断一下当前编号是否存在
bzoj 5017 [Snoi2017]炸弹的更多相关文章
- [bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑
5017: [Snoi2017]炸弹 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 608 Solved: 190[Submit][Status][ ...
- [LOJ#2255][BZOJ5017][Snoi2017]炸弹
[LOJ#2255][BZOJ5017][Snoi2017]炸弹 试题描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: ...
- [SNOI2017]炸弹[线段树优化建图]
[SNOI2017]炸弹 线段树优化建图,然后跑一边tarjan把点全部缩起来,炸一次肯定是有连锁反应的所以整个连通块都一样-于是就可以发现有些是只有单向边的不能忘记更新,没了. #include & ...
- bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)
https://www.lydsy.com/JudgeOnline/problem.php?id=5017 暴力: 对于每一个炸弹,枚举所有的炸弹,看它爆炸能不能引爆那个炸弹 如果能,由这个炸弹向引爆 ...
- bzoj 5017 炸弹
题目大意: 直线上有n个炸弹有坐标x和半径r 当一个炸弹被引爆时 若有炸弹的坐标在该炸弹坐标+-r范围内则另一个炸弹也被引爆 求先引爆每一个炸弹最终会引爆多少炸弹 思路: 可以想到n平方连边然后tar ...
- BZOJ5017题解SNOI2017炸弹--玄学递推
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5017 分析 老师讲课谈到了这道题,课上想出了个连边建图然后乱搞的操作,被老师钦定的递推方 ...
- bzoj5017 [Snoi2017]炸弹 (线段树优化建图+)tarjan 缩点+拓扑排序
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=5017 题解 这个题目方法挺多的. 线段树优化建图 线段树优化建图的做法应该挺显然的,一个炸弹能 ...
- [SNOI2017]炸弹
嘟嘟嘟 这题有一些别的瞎搞神奇做法,而且复杂度似乎更优,不过我为了练线段树,就乖乖的官方正解了. 做法就是线段树优化建图+强连通分量缩点+DAGdp. 如果一个炸弹\(i\)能引爆另一个炸弹\(j\) ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
随机推荐
- 李洪强iOS开发之-实现点击单行View显示和隐藏Cell
李洪强iOS开发之-实现点击单行View显示和隐藏Cell 实现的效果: .... ....
- (转载)常用的Mysql数据库操作语句大全
打开CMD,进入数据库命令:mysql -hlocalhost -uroot -p 退出数据库:exit 用户管理: 1.新建用户: >CREATE USER name IDENTIFIED B ...
- SenTestingKit.framework的报错!
本文转载至http://www.cocoachina.com/ask/questions/show/106912 ld: building for iOS Simulator, but linking ...
- HTML 客户端存储
在客户端存储数据 HTML5 提供了两种在客户端存储数据的新方法: localStorage - 没有时间限制的数据存储 sessionStorage - 针对一个 session 的数据存储 之前, ...
- linux 设备驱动程序中的一些关联性思考
首先,个人感觉设备驱动程序与应用程序中的文件操作隔得有点远,用户空间不论是直接使用系统调用还是库函数都是通过系统调用的接口进入内核空间代码的.但是看过一个博客的分析整个过程,感觉中间层太过麻烦,必须经 ...
- 概率dp集合
bzoj1076 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后 ...
- POJ 1861 Network (Kruskal算法+输出的最小生成树里最长的边==最后加入生成树的边权 *【模板】)
Network Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 14021 Accepted: 5484 Specia ...
- Hihocoder #1014 : Trie树 (字典数树统计前缀的出现次数 *【模板】 基于指针结构体实现 )
#1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助, ...
- POJ3273 Monthly Expense —— 二分
题目链接:http://poj.org/problem?id=3273 Monthly Expense Time Limit: 2000MS Memory Limit: 65536K Tota ...
- 利用百度地图API制作房产酒店地图
摘要: 想亲手制作一张酷讯.去哪儿.安居客.链接地产那样的房产.酒店地图麼?那赶快来学习吧.(以酷讯为例,如下图) 更多成功案例请点击:http://dev.baidu.com/wiki/map/in ...