zoukankan      html  css  js  c++  java
  • [SNOI2017]炸弹

    Solution

    一个显然的做法是把一个点能到达的所有点连上边,然后缩点,形成一个 DAG,在 DAG 上统计能到达的点的个数,转换成可达性统计,用 bitset 随便维护一下就可以了。(大概能得 30 分?)
    这个做法有两个问题,边的数量级是 (O(n^2)) 的,bitset 的空间复杂度也是 (O(frac{n^2}{32})) 的。第一个问题的解决方法就是建边优化。考虑到连的边是一个区间,所以直接线段树建图就可以了。同样利用这个区间的性质。对任意三个点 (u<v<p),那么若 (p) 能到达 (u) 那一定能到达 (v)。所以对于每一个点,只需要统计它能到达的区间的左右端点即可,一遍拓扑排序就可以解决。

    #include<stdio.h>
    #include<algorithm>
    #include<string.h>
    using namespace std;
    #define N 1000007
    #define int long long
    #define ll long long
    #define lid id<<1
    #define rid id<<1|1
    #define Mod 1000000007
    #define re register
    
    inline ll read(){
        ll x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    struct E{
        int next,to;
    }e[N*20];
    
    int seg[N],head[N*4],cnt=0;
    int dfn[N*4],c[N*4],low[N*4],sta[N*4],top=0,ti=0,scc=0;
    int X[N*20],Y[N*20],n,L[N*4],R[N*4];
    ll a[N],r_[N];
    
    inline void add(int id,int to){
        e[++cnt]=(E){head[id],to};
        X[cnt]=id,Y[cnt]=to;
        head[id]=cnt;
    }
    
    inline void build(int id,int lf,int rf){
        if(lf==rf) seg[lf]=id;
        else{
            int mid=(lf+rf)>>1;
            build(lid,lf,mid);
            build(rid,mid+1,rf);
            add(id,lid),add(id,rid);
        }
    }
    
    int l,r,pos;
    inline void link(int id,int lf,int rf){
        if(l<=lf&&rf<=r){
            if(pos==id) return ;
            add(pos,id);
        }else{
            int mid=(lf+rf)>>1;
            if(l<=mid) link(lid,lf,mid);
            if(r>mid) link(rid,mid+1,rf);
        }
    }
    
    inline void tarjan(int u){
        dfn[u]=low[u]=++ti;
        sta[++top]=u;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(!c[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            scc++;
            int y;
            do{
                y=sta[top--];
                c[y]=scc;
            }while(y!=u);
        }
    }
    
    bool vis[N*4];
    inline void dfs(int u){
        vis[u]=1;
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(!vis[v]) dfs(v);
            if(!L[v]) continue;
            L[u]=min(L[u],L[v]);
            R[u]=max(R[u],R[v]);
        }
    }
    
    struct Node{
        ll x,r;
        bool operator <(const Node &X) const{return x<X.x;}
    }A[N];
    
    void build2(int id,int lf,int rf){
        L[c[id]]=min(L[c[id]],lf);
        R[c[id]]=max(R[c[id]],rf);
        if(lf!=rf){
            int mid=(lf+rf)>>1;
            build2(lid,lf,mid);
            build2(rid,mid+1,rf);
        }
    }
    
    signed main(){
    //    freopen("Alphawithomega.in","r",stdin);
    //    freopen("Alphawithomega.out","w",stdout);
        n=read();
        build(1,1,n);
        for(re int i=1;i<=n;i++) A[i].x=read(),A[i].r=read();
        sort(A+1,A+1+n);
        for(re int i=1;i<=n;i++) a[i]=A[i].x,r_[i]=A[i].r;
        for(re int i=1;i<=n;i++){
            if(!r_[i]) continue;
            l=lower_bound(a+1,a+1+n,a[i]-r_[i])-a;
            r=upper_bound(a+1,a+1+n,a[i]+r_[i])-a-1;
            if(l<1) l=1; if(r>n) r=n; pos=seg[i];
            link(1,1,n);
        }
        for(re int i=1;i<=seg[n];i++)
            if(!dfn[i]) tarjan(i);
        memset(head,0,sizeof(head));
        int tmp=cnt; cnt=0;
        for(re int i=1;i<=tmp;i++)
            if(c[X[i]]!=c[Y[i]]) add(c[X[i]],c[Y[i]]);
        memset(L,0x3f3f3f3f,sizeof(L));
        build2(1,1,n);
        ll ret=0,sum=0;
        for(re int i=1;i<=scc;i++) dfs(i);
        for(re ll i=1;i<=n;i++)
            ret=(ret+i*(R[c[seg[i]]]-L[c[seg[i]]]+1)%Mod)%Mod;
        printf("%lld",ret);
    }
    /*
    4
    1 1
    5 1
    6 5
    15 15
    */
    
  • 相关阅读:
    希腊字母写法
    The ASP.NET MVC request processing line
    lambda aggregation
    UVA 10763 Foreign Exchange
    UVA 10624 Super Number
    UVA 10041 Vito's Family
    UVA 10340 All in All
    UVA 10026 Shoemaker's Problem
    HDU 3683 Gomoku
    UVA 11210 Chinese Mahjong
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14123969.html
Copyright © 2011-2022 走看看