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
    */
    
  • 相关阅读:
    ucos信号量
    uC/OSII 常用函数参考手册
    GPS NMEA0183协议详解
    为sql server 表数据生成创建的储存过程(生成insert 脚本)
    安装SQL2008,提示删除SQL2005Express工具的解决方法
    intel hex 文件格式解密
    C语言:I/O
    C语言基础
    摆脱IDE进行时. . .
    对WinForm的App.config文件进行加密
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14123969.html
Copyright © 2011-2022 走看看