loj #2255. 「SNOI2017」炸彈

#2255. 「SNOI2017」炸彈

題目描述

在一條直線上有 NNN 個炸彈,每一個炸彈的座標是 XiX_iXi​​,爆炸半徑是 RiR_iRi​​,當一個炸彈爆炸時,若是另外一個炸彈所在位置 XjX_jXj​​ 知足:html

Xi−Ri≤Xj≤Xi+Ri X_i-R_i\leq X_j \leq X_i+R_iXi​​Ri​​Xj​​Xi​​+Ri​​

那麼,該炸彈也會被引爆。node

如今,請你幫忙計算一下,先把第 iii 個炸彈引爆,將引爆多少個炸彈呢?ios

輸入格式

第一行,一個數字 NNN,表示炸彈個數。 第 2∼N+12\sim N+12N+1 行,每行 222 個數字,表示 XiX_iXi​​,RiR_iRi​​,保證 XiX_iXi​​ 嚴格遞增。ide

輸出格式

一個數字,表示 ∑i=1ni×\sum \limits_{i=1}^n i\timesi=1n​​i× 炸彈 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\times 1+2\times 3+3\times 3+4\times 4=321×1+2×3+3×3+4×4=32。ui

數據範圍與提示

20%20\%20% 的數據:N≤100N\leq 100N100
50%50\%50% 的數據:N≤1000N\leq 1000N1000
80%80\%80% 的數據:N≤100000N\leq 100000N100000
100%100\%100% 的數據:N≤500000N\leq 500000N500000,−1018≤Xi≤1018-10^{18}\leq X_i\leq 10^{18}1018​​Xi​​1018​​,0≤Ri≤2×10180\leq R_i\leq 2\times 10^{18}0Ri​​2×1018​​
spa

數據範圍與原題相同,但測試數據由本站會員自制,並不是原數據。
時限已按照評測機速度調整,原題時限爲2000ms,省選評測時調整爲4000ms,這裏按4000ms調整。code

原題評測環境爲Windows,棧空間2MB。htm

 

#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);
}
50分 暴力
#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;
}
100分
相關文章
相關標籤/搜索