zoukankan      html  css  js  c++  java
  • bzoj5017: [Snoi2017]炸弹

    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。 

    如果一个炸弹能引爆另一个,就对应连一条有向边,询问即为查询每个点能到达的点中最左和最右分别是哪一个。由于边数较多,需要线段树优化建图,然后用tarjan将强连通分量缩点,缩点后在得到的DAG上逆拓扑序递推一下。时间复杂度O(nlogn),空间复杂度O(n)(线段树上的区间连边不需要记录,只要动态计算即可)。

    #include<bits/stdc++.h>
    typedef long long i64;
    const int P=1e9+7,N=5e5+7;
    char buf[N*50],*ptr=buf-1;
    i64 _(){
        i64 x=0;
        int c=*++ptr,f=1;
        while(c<48)c=='-'?f=-1:0,c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x*f;
    }
    int n,mx,tk=0,ss[1<<20|111],sp=0,ans=0;
    i64 xs[N],rs[N];
    void mins(int&a,int b){if(a>b)a=b;}
    void maxs(int&a,int b){if(a<b)a=b;}
    struct node{
        int l,r,dfn,low;
        bool in;
        void chk0(node&w){
            mins(l,w.l),maxs(r,w.r);
        }
        void chk1(node&w){
            mins(low,w.low);
            chk0(w);
        }
        void chk2(node&w){
            if(w.in)mins(low,w.dfn);
            chk0(w);
        }
    }ns[1<<20|111];
    void tj(int);
    void tje(int w,int u){
        if(!ns[u].dfn){
            tj(u);
            ns[w].chk1(ns[u]);
        }else ns[w].chk2(ns[u]);
    }
    void tj(int w){
        ns[w].dfn=ns[w].low=++tk;
        ns[w].in=1;
        ss[++sp]=w;
        if(!ns[w].l)ns[w].l=n+1;
        if(w<mx){
            tje(w,w<<1);
            tje(w,w<<1^1);
        }else{
            for(int l=mx+ns[w].l-1,r=mx+ns[w].r+1;r-l>1;l>>=1,r>>=1){
                if(~l&1)tje(w,l+1);
                if(r&1)tje(w,r-1);
            }
        }
        if(ns[w].dfn==ns[w].low){
            int u;
            do{
                ns[u=ss[sp--]].in=0;
                ns[u].chk0(ns[w]);
            }while(u!=w);
        }
    }
    int main(){
        fread(buf,1,sizeof(buf),stdin);
        n=_();
        for(int i=1;i<=n;++i)xs[i]=_(),rs[i]=_();
        for(mx=1;mx<=n+2;mx<<=1);
        for(int i=1;i<=n;++i){
            ns[mx+i].l=std::lower_bound(xs+1,xs+n+1,xs[i]-rs[i])-xs;
            ns[mx+i].r=std::upper_bound(xs+1,xs+n+1,xs[i]+rs[i])-xs-1;
        }
        tj(1);
        for(int i=1;i<=n;++i){
            node&w=ns[mx+i];
            ans=(ans+i64(i)*(w.r-w.l+1))%P;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    博客园风格简单修饰(Do It Yourself)
    十大经典排序算法
    物流BOS
    算法设计
    牛客网刷题
    关于上网的问题
    Lucene&Solr
    SSM综合练习
    四十八:WAF绕过-权限控制之代码混淆及行为造轮子
    四十七:WAF绕过-漏洞发现之代理池指纹被动探针
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7501650.html
Copyright © 2011-2022 走看看