5017: [Snoi2017]炸弹
Time Limit: 30 Sec Memory Limit: 512 MB
Submit: 243 Solved: 95
[Submit][Status][Discuss]
Description
在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足:
Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆。
现在,请你帮忙计算一下,先把第 i 个炸弹引爆,将引爆多少个炸弹呢?
Input
第一行,一个数字 N,表示炸弹个数。
第 2∼N+1行,每行 2 个数字,表示 Xi,Ri,保证 Xi 严格递增。
N≤500000
−10^18≤Xi≤10^18
0≤Ri≤2×10^18
Output
一个数字,表示Sigma(i*炸弹i能引爆的炸弹个数),1<=i<=N mod10^9+7。
Sample Input
4
1 1
5 1
6 5
15 15
Sample Output
32
HINT
Source
sol:
比较简单,没有solution,这份代码在bz上面一直compiling然后被kill但是loj能过。
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<vector>
using namespace std;
inline int read()
{
char c;
bool pd=0;
while((c=getchar())>'9'||c<'0')
if(c=='-') pd=1;
int res=c-'0';
while((c=getchar())>='0'&&c<='9')
res=(res<<3)+(res<<1)+c-'0';
return pd?-res:res;
}
const int N=2100000;
const int M=21000000;
vector<int> q[N];
typedef long long ll;
struct cc
{
ll x,y;
friend inline bool operator <(const cc &a,const cc &b)
{
return a.x<b.x;
}
}a[N];
int tot,fir[N],go[M],nex[M],from[M];
inline void add(int x,int y)
{
nex[++tot]=fir[x];fir[x]=tot;go[tot]=y;from[tot]=x;
}
int low[N],dfn[N],tim,sta[N];
bool vis[N];
int id[N],ID;
inline void tarjan(int u)
{
dfn[u]=low[u]=++tim;
sta[++sta[0]]=u;
vis[u]=1;
int e,v;
for(e=fir[u];v=go[e],e;e=nex[e])
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(vis[v])
low[u]=min(low[u],dfn[v]);
if(low[u]==dfn[u])
{
++ID;
do
{
v=sta[sta[0]--];
id[v]=ID;
vis[v]=0;
q[ID].push_back(v);
}while(v!=u);
}
}
inline void modify(int k,int l,int r,int L,int R,int x)
{
if(L<=l&&r<=R)
{
add(x,k);
return;
}
int mid=l+r>>1;
if(mid>=L) modify(k<<1,l,mid,L,R,x);
if(mid< R) modify(k<<1|1,mid+1,r,L,R,x);
}
int pos[N];
inline void build(int k,int l,int r)
{
if(l==r)
{
pos[l]=k;
return;
}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
add(k,k<<1);
add(k,k<<1|1);
}
int sizew,nn,n;
int L[N],R[N],tol[N],tor[N];
int deg[N];
const int pyz=1e9+7;
int tots,firs[N],gos[M];
inline void adds(int x,int y)
{
nex[++tots]=firs[x];firs[x]=tots;gos[tots]=y;
}
int main()
{
// freopen("5017.in","r",stdin);
n=read();
for(int i=1;i<=n;++i)
scanf("%lld%lld",&a[i].x,&a[i].y);
for(sizew=1;sizew<n;sizew<<=1);
nn=sizew<<1;
build(1,1,sizew);
for(int i=1;i<=n;++i)
{
cc t=(cc){a[i].x-a[i].y};
tol[pos[i]]=L[pos[i]]=lower_bound(a+1,a+1+n,t)-a;
t.x=a[i].x+a[i].y;
tor[pos[i]]=R[pos[i]]=upper_bound(a+1,a+1+n,t)-a-1;
modify(1,1,sizew,tol[pos[i]],tor[pos[i]],pos[i]);
}
for(int i=1;i<=nn;++i)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=ID;++i)
{
vector<int>::iterator it;
int e,v,u;
L[i]=n;
R[i]=0;
for(it=q[i].begin();it!=q[i].end();++it)
{
u=*it;
if(u>=pos[1])
{
L[i]=min(L[i],tol[u]);
R[i]=max(R[i],tor[u]);
}
}
}
for(int i=1;i<=tot;++i)
{
adds(go[i],from[i]);
if(id[go[i]]!=id[from[i]]) deg[id[from[i]]]++;
}
sta[0]=0;
for(int i=1;i<=ID;++i)
if(!deg[i]) sta[++sta[0]]=i;
int t=0,ans=0;
while(t<sta[0])
{
int i=sta[++t];
vector<int>::iterator it;
int e,v,u;
for(it=q[i].begin();it!=q[i].end();++it)
{
u=*it;
for(e=firs[u];v=gos[e],e;e=nex[e])
if(id[u]!=id[v])
{
if(!(--deg[id[v]])) sta[++sta[0]]=id[v];
L[id[v]]=min(L[id[v]],L[i]);
R[id[v]]=max(R[id[v]],R[i]);
}
}
}
for(int i=1;i<=n;++i)
ans=((ll)ans+(ll)i*(R[id[pos[i]]]-L[id[pos[i]]]+1)%pyz)%pyz;
printf("%d\n",ans);
}