题好数据水系列,网上的十几行神仙解法A了原数据。

这道题要用到线段数优化建图的知识。然而考试考到这道题时我还不会。

我们设分别表示每个炸弹向左和向右最远能炸到哪个炸弹。很容易想到一个思路,就是每个炸弹都连边连向它能直接炸的所有炸弹,然后tarjan缩块后DAG图上DP。如果a到b有边,那么就能用b的更新。但是直接连边显然是不行的。

我们仔细思考一下就会发现,一个炸弹能直接炸炸弹一定是一段连续的区间,这就给了我们想象的空间。我们就建一颗区间线段树,每个点的代表元就是对应的叶子节点。我们将所有节点(除了叶子节点)连向两个儿子节点。然后考虑一个炸弹,假设它能直接引爆的区间是,那我们就用类似于线段树区间修改的方法将递归过程中遇到的包含于的区间与的代表元连边。然后就是tarjan的事了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#define ll long long
#define N 2000005 using namespace std;
inline ll Get() {ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} const ll mod=1e9+7;
struct tree {
int l,r;
int lx,rx;
}tr[N];
struct load {int to,next;}s[N*15];
int h[N],cnt;
void add(int i,int j) {
s[++cnt]=(load) {j,h[i]};h[i]=cnt;
}
int tot;
void Link(int fr,int v,int l,int r) {
if(tr[v].l>r||tr[v].r<l) return ;
if(l<=tr[v].l&&tr[v].r<=r) {
if(fr!=v) add(fr,v);
return ;
}
Link(fr,v<<1,l,r);
Link(fr,v<<1|1,l,r);
}
int pos[N];
void build(int v,int l,int r) {
tr[v].lx=tr[v].l=l;
tr[v].rx=tr[v].r=r;
tot=max(tot,v);
if(l==r) return pos[l]=v,void();
int mid=l+r>>1;
build(v<<1,l,mid),build(v<<1|1,mid+1,r);
add(v,v<<1),add(v,v<<1|1);
}
int n;
ll x[N],r[N];
vector<ll>p;
int low[N],dfn[N],id;
int st[N],bel[N],scc;
int lx[N],rx[N];
bool ins[N];
void tarjan(int v) {
low[v]=dfn[v]=++id;
st[++st[0]]=v;
ins[v]=1;
for(int i=h[v];i;i=s[i].next) {
int to=s[i].to;
if(!dfn[to]) {
tarjan(to);
low[v]=min(low[v],low[to]);
} else if(ins[to]) low[v]=min(low[v],dfn[to]);
}
if(low[v]==dfn[v]) {
scc++;
while(1) {
int j=st[st[0]--];
ins[j]=0;
bel[j]=scc;
if(j==v) break;
}
}
}
vector<int>e[N];
int d[N];
bool vis[N];
void dfs(int v) {
vis[v]=1;
for(int i=0,s=e[v].size();i<s;i++) {
int to=e[v][i];
if(!vis[to]) dfs(to);
lx[v]=min(lx[v],lx[to]);
rx[v]=max(rx[v],rx[to]);
}
}
ll ans;
int main() {
int size=40<<20;//40M
__asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));
n=Get();
build(1,1,n);
for(int i=1;i<=n;i++) {
x[i]=Get(),r[i]=Get();
p.push_back(x[i]);
}
for(int i=1;i<=n;i++) {
int Lx=lower_bound(p.begin(),p.end(),x[i]-r[i])-p.begin();
int Rx=upper_bound(p.begin(),p.end(),x[i]+r[i])-p.begin()-1;
lx[i]=Lx+1,rx[i]=Rx+1;
Link(pos[i],1,lx[i],rx[i]);
}
for(int i=1;i<=tot;i++) {
if(!dfn[i]) tarjan(i);
} for(int i=1;i<=scc;i++) lx[i]=n+1,rx[i]=0;
for(int i=1;i<=tot;i++) {
lx[bel[i]]=min(lx[bel[i]],tr[i].lx);
rx[bel[i]]=max(rx[bel[i]],tr[i].rx);
for(int j=h[i];j;j=s[j].next) {
int to=s[j].to;
if(bel[i]!=bel[to]) {
e[bel[i]].push_back(bel[to]);
d[bel[to]]++;
}
}
}
for(int i=1;i<=scc;i++)
if(!d[i]) dfs(i);
for(int i=1;i<=n;i++) {
ans=(ans+i*(rx[bel[pos[i]]]-lx[bel[pos[i]]]+1+mod)%mod)%mod;
}
cout<<ans;
exit(0);
return 0;
}

BSOJ 5603 -- 【SNOI2017】炸弹的更多相关文章

  1. [bzoj5017][Snoi2017]炸弹 tarjan缩点+线段树优化建图+拓扑

    5017: [Snoi2017]炸弹 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 608  Solved: 190[Submit][Status][ ...

  2. [LOJ#2255][BZOJ5017][Snoi2017]炸弹

    [LOJ#2255][BZOJ5017][Snoi2017]炸弹 试题描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: ...

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

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

  4. BZOJ5017题解SNOI2017炸弹--玄学递推

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=5017 分析 老师讲课谈到了这道题,课上想出了个连边建图然后乱搞的操作,被老师钦定的递推方 ...

  5. [SNOI2017]炸弹

    嘟嘟嘟 这题有一些别的瞎搞神奇做法,而且复杂度似乎更优,不过我为了练线段树,就乖乖的官方正解了. 做法就是线段树优化建图+强连通分量缩点+DAGdp. 如果一个炸弹\(i\)能引爆另一个炸弹\(j\) ...

  6. bzoj千题计划311:bzoj5017: [Snoi2017]炸弹(线段树优化tarjan构图)

    https://www.lydsy.com/JudgeOnline/problem.php?id=5017 暴力: 对于每一个炸弹,枚举所有的炸弹,看它爆炸能不能引爆那个炸弹 如果能,由这个炸弹向引爆 ...

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

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

  8. bzoj5017: [Snoi2017]炸弹

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

  9. BZOJ5017 Snoi2017炸弹(线段树+强连通分量+缩点+传递闭包)

    容易想到每个炸弹向其能引爆的炸弹连边,tarjan缩点后bitset传递闭包.进一步发现每个炸弹能直接引爆的炸弹是一段连续区间,于是线段树优化建图即可让边的数量降至O(nlogn).再冷静一下由于能间 ...

随机推荐

  1. 近20个绚丽实用的jQuery/CSS3侧边栏菜单(转载)

    http://developer.51cto.com/art/201510/493530.htm 近20个绚丽实用的jQuery/CSS3侧边栏菜单 jQuery作为一款主流的JavaScript前端 ...

  2. nginx ssl证书

    server { listen ; server_name xxx.com; root "/home/www/website"; ssl on; ssl_certificate / ...

  3. Java高并发--安全发布对象

    Java高并发--安全发布对象 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 发布对像:使一个对象能够被当前范围之外的对象使用. 对象逸出:一种错误的发布.当一个对象 ...

  4. Netty实战二之自己的Netty应用程序

    接下来我们将展示如何构建一个基于Netty的客户端和服务器,程序很简单:客户端将消息发送给服务器,而服务器再将消息回送给客户端,这将是一个对你而言很重要的第一个netty的实践经验. 1.设置开发环境 ...

  5. JavaScript 比较 和 逻辑运算符

    比较运算符 比较运算符在逻辑语句中使用,以测定变量或值是否相等. === 绝对等于(值和类型均相等) !=  不等于 !==  不绝对等于(值和类型有一个不相等,或两个都不相等) >  大于 & ...

  6. 【代码笔记】Web-Javascript-Javascript函数

    一,效果图. 二,代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  7. HTML元素被定义为块级元素或内联元素。那么什么是块级元素,什么是内联元素呢

    块级元素(block)特性: 块级元素在浏览器显示时,通常会以新行来开始(和结束). 宽度(width).高度(height).内边距(padding)和外边距(margin)都可控制;就像以前用到的 ...

  8. win10电脑怎么录制视频 电脑录制视频软件

    win10电脑怎么录制视频?相信不少网友正在面临这个疑惑.现如今是网络信息科技时代,快速传播信息的途径和方式有很多种.其中,通过录制电脑视频,可以制作视频教程.游戏解说,还可以录制在线视频存储影视资源 ...

  9. 自定义View类

    一.如何创建自定义的View类 ①.创建一个继承android.view.View类的Java类,并且重写构造方法(至少需要重写一个构造方法) ②.根据需要重写其他方法 ③.在项目的活动中,创建并实例 ...

  10. Okhttp3请求网络开启Gzip压缩

    前沿 首先OkHttp3是支持Gzip解压缩的,不过我们要明白,它是支持我们在发起请求的时候自动加入header,Accept-Encoding: gzip,而我们的服务器返回的时候header中有C ...