#2255. 「SNOI2017」炸弹
题目描述
在一条直线上有 NNN 个炸弹,每个炸弹的坐标是 XiX_iXi,爆炸半径是 RiR_iRi,当一个炸弹爆炸时,如果另一个炸弹所在位置 XjX_jXj 满足:
Xi−Ri≤Xj≤Xi+Ri X_i-R_ileq X_j leq X_i+R_iXi−Ri≤Xj≤Xi+Ri那么,该炸弹也会被引爆。
现在,请你帮忙计算一下,先把第 iii 个炸弹引爆,将引爆多少个炸弹呢?
输入格式
第一行,一个数字 NNN,表示炸弹个数。 第 2∼N+12sim N+12∼N+1 行,每行 222 个数字,表示 XiX_iXi,RiR_iRi,保证 XiX_iXi 严格递增。
输出格式
一个数字,表示 ∑i=1ni×sum limits_{i=1}^n i imesi=1∑ni× 炸弹 iii 能引爆的炸弹个数 mod109+7。
样例
样例输入
4
1 1
5 1
6 5
15 15
样例输出
32
样例解释
炸弹 1,2,3,41,2,3,41,2,3,4 分别能引爆 1,3,3,41,3,3,41,3,3,4 个炸弹,所以答案是 1×1+2×3+3×3+4×4=321 imes 1+2 imes 3+3 imes 3+4 imes 4=321×1+2×3+3×3+4×4=32。
数据范围与提示
20%20\%20% 的数据:N≤100Nleq 100N≤100
50%50\%50% 的数据:N≤1000Nleq 1000N≤1000
80%80\%80% 的数据:N≤100000Nleq 100000N≤100000
100%100\%100% 的数据:N≤500000Nleq 500000N≤500000,−1018≤Xi≤1018-10^{18}leq X_ileq 10^{18}−1018≤Xi≤1018,0≤Ri≤2×10180leq R_ileq 2 imes 10^{18}0≤Ri≤2×1018
数据范围与原题相同,但测试数据由本站会员自制,并非原数据。
时限已按照评测机速度调整,原题时限为2000ms,省选评测时调整为4000ms,这里按4000ms调整。
原题评测环境为Windows,栈空间2MB。
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 1010 #define mod 1000000007 using namespace std; long long X[maxn],R[maxn]; int n,head[maxn],num; bool vis[maxn]; struct node{int to,pre;}e[maxn*maxn]; void Insert(int from,int to){ e[++num].to=to; e[num].pre=head[from]; head[from]=num; } long long qread(){ long long i=0,j=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();} while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();} return i*j; } int bfs(int x){ int res=1; memset(vis,0,sizeof(vis)); queue<int>q;q.push(x);vis[x]=1; while(!q.empty()){ int now=q.front();q.pop(); for(int i=head[now];i;i=e[i].pre){ int to=e[i].to; if(!vis[to]){ res++; vis[to]=1; q.push(to); } } } return res; } int main(){ n=qread(); for(int i=1;i<=n;i++)X[i]=qread(),R[i]=qread(); for(int i=1;i<=n;i++){ for(int j=i-1;j>=1;j--){ if(X[i]-R[i]<=X[j])Insert(i,j); else break; } for(int j=i+1;j<=n;j++){ if(X[i]+R[i]>=X[j])Insert(i,j); else break; } } int ans=0; for(int i=1;i<=n;i++){ int num=bfs(i); ans=(ans+1LL*i*num%mod)%mod; } printf("%d",ans); }
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 500010 #define mod 1000000007 using namespace std; long long X[maxn],R[maxn]; int n,l[maxn],r[maxn],ans; long long qread(){ long long i=0,j=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();} while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();} return i*j; } int main(){ n=qread(); for(int i=1;i<=n;i++)X[i]=qread(),R[i]=qread(); for(int i=1;i<=n;i++){ l[i]=i; while(l[i]>1&&X[i]-X[l[i]-1]<=R[i]) l[i]=l[l[i]-1],R[i]=max(R[i],R[l[i]]-X[i]+X[l[i]]); } for(int i=n;i>=1;i--){ r[i]=i; while(r[i]<n&&X[r[i]+1]-X[i]<=R[i]) r[i]=r[r[i]+1],l[i]=min(l[i],l[r[i]]); } for(int i=1;i<=n;i++)ans=(ans+1LL*i*(r[i]-l[i]+1)%mod)%mod; printf("%d",ans); return 0; }