zoukankan      html  css  js  c++  java
  • CF786B Legacy

    CF786B Legacy

    题意:
    给定(n)个点
    一共有(m)个连边,边有三种。
    1.从(u_i)(v_i)的一条长度为(w_i)的边。
    2.从(u_i)([l,r])的一条长度为(w_i)的边。
    3.从([l,r])(v_i)的一条长度为(w_i)的边。

    问从(s)到每一个点的最短路。
    (n,m<=10^5)


    很有意思的题目

    显然不可以暴力连边,我们可以拿线段树的思想,让线段树的一个区间代表一个点。

    拿两颗线段树分别维护区间连点和点连区间

    以点连区间为例,直接拿点连树1的区间。而树1上面的边可以以费用0走到孩子节点。

    对应区间连点,就是那树2的区间直接连点。而树2上面的边可以以费用0走到父亲节点。

    连接树1树2就行了


    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #define ls ch[now][0]
    #define rs ch[now][1]
    #define ll long long
    using namespace std;
    const int N=100010;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    int head[N<<3],to[N<<4],Next[N<<4],cnt;
    int n,m,s,ch[N<<3][2],tot,typ;
    ll edge[N<<4];
    void add(int u,int v,ll w)
    {
        edge[++cnt]=w;to[cnt]=v;Next[cnt]=head[u];head[u]=cnt;
    }
    int build1(int l,int r)
    {
        if(l==r) return l;
        int now=++tot;
        int mid=l+r>>1;
        ls=build1(l,mid);
        rs=build1(mid+1,r);
        add(now,ls,0);
        add(now,rs,0);
        return now;
    }
    int build2(int id,int l,int r)
    {
        if(l==r) return l;
        int now=++tot;
        int mid=l+r>>1;
        ls=build2(ch[id][0],l,mid);
        rs=build2(ch[id][1],mid+1,r);
        add(ls,now,0);
        add(rs,now,0);
        add(id,now,0);
        return now;
    }
    void connect(int now,int l,int r,int L,int R,int pos,ll w)
    {
        if(l==L&&r==R)
        {
            if(typ==1)  add(pos,now,w);
            else add(now,pos,w);
            return;
        }
        int mid=L+R>>1;
        if(r<=mid)
            connect(ls,l,r,L,mid,pos,w);
        else if(l>mid)
            connect(rs,l,r,mid+1,R,pos,w);
        else
            connect(ls,l,mid,L,mid,pos,w),connect(rs,mid+1,r,mid+1,R,pos,w);
    }
    int root[2];
    void init()
    {
        scanf("%d%d%d",&n,&m,&s);
        tot=n;
        root[0]=build1(1,n);
        root[1]=build2(root[0],1,n);
        int opt,u,v,l,r;ll w;
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&opt);
            if(opt==1)
            {
                scanf("%d%d%lld",&u,&v,&w);
                add(u,v,w);
            }
            else if(opt==2)
            {
                scanf("%d%d%d%lld",&u,&l,&r,&w);//点连区间
                typ=1;
                connect(root[0],l,r,1,n,u,w);
            }
            else
            {
                scanf("%d%d%d%lld",&v,&l,&r,&w);
                typ=0;
                connect(root[1],l,r,1,n,v,w);
            }
        }
    }
    queue <int> q;
    ll dis[N<<3];
    int used[N<<3];
    void work()
    {
        memset(dis,0x3f,sizeof(dis));
        dis[s]=0;
        q.push(s);
        while(!q.empty())
        {
            int u=q.front();
            used[u]=0;
            q.pop();
            for(int i=head[u];i;i=Next[i])
            {
                int v=to[i];
                ll w=edge[i];
                if(dis[v]>dis[u]+w)
                {
                    dis[v]=dis[u]+w;
                    if(!used[v])
                    {
                        used[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==inf)
                printf("-1 ");
            else
                printf("%lld ",dis[i]);
        }
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    
    

    2018.7.20

  • 相关阅读:
    Solaris引导和关闭
    systemctl
    [Poj3281]Dining(最大流)
    [Poj1149]Pigs(最大流)
    [Bzoj2588]Count on a tree(主席树+LCA)
    [BZOJ3524]区间问题(主席树)
    [Poj2761]Feed the dogs(主席树)
    [BZOJ1597][Usaco2008 Mar]土地购买(斜率优化)
    [BSOJ2684]锯木厂选址(斜率优化)
    [Hdu3507]Print Article(斜率优化)
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9342150.html
Copyright © 2011-2022 走看看