[bzoj5017][線段樹優化建邊]炸彈

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);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章