zoukankan      html  css  js  c++  java
  • CF786B Legacy 线段树优化建图 + spfa

    CodeForces 786B

    Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们。因此Rick想在坏人们捉到他之前把他的遗产留给Morty。

    在宇宙中一共有n个星球标号为1到n。Rick现在身处于标号为s的星球(地球)但是他不知道Morty在哪里。众所周知,Rick有一个传送枪,他用这把枪可以制造出一个从他所在的星球通往其他星球(也包括自己所在的星球)的单行道路。但是由于他还在用免费版,因此这把枪的使用是有限制的。

    默认情况下他不能用这把枪开启任何传送门。在网络上有q个售卖这些传送枪的使用方案。每一次你想要实施这个方案时你都可以购买它,但是每次购买后只能使用一次。每个方案的购买次数都是无限的。

    网络上一共有三种方案可供购买: 1.开启一扇从星球v到星球u的传送门; 2.开启一扇从星球v到标号在[l,r]区间范围内任何一个星球的传送门。(即这扇传送门可以从一个星球出发通往多个星球) 3.开启一扇从标号在[l,r]区间范围内任何一个星球到星球v的传送门。(即这扇传送门可以从多个星球出发到达同一个星球)

    Rick并不知道Morty在哪儿,但是Unity将要通知他Morty的具体位置,并且他想要赶快找到通往所有星球的道路各一条并立刻出发。因此对于每一个星球(包括地球本身)他想要知道从地球到那个星球所需的最小钱数。

    输入数据: 输入数据的第一行包括3个整数n,q和s(1<=n,q<=10^5,1<=s<=n)分别表示星球的数目,可供购买的方案数目以及地球的标号。

    接下来的q行表示q种方案。 1.输入1 v u w表示第一种方案,其中v,u意思同上,w表示此方案价格。 2.输入2 v l r w表示第二种方案,其中v,l,r意思同上,w表示此方案价格。 2.输入3 v l r w表示第三种方案,其中v,l,r意思同上,w表示此方案价格。 (1<=v,u,l,r<=n,1<=w<=10^9)

    输出格式: 输出一行用空格隔开的n个整数分别表示从地球到第i个星球所需的最小钱数。

    说明: 在第一组测试样例里,Rick可以先购买第4个方案再购买第2个方案从而到达标号为2的星球.

    题解:

    线段树优化建图模板题 

    建立两颗线段树,这两颗线段树共用编号相同的叶子节点 

    在线段树对应区间上连一连就好了 

    #include<bits/stdc++.h>
    #define setIO(s) freopen(s".in","r",stdin) 
    #define maxn 4000000 
    #define inf 100000000000000  
    #define lson t[now].ls 
    #define rson t[now].rs   
    #define ll long long 
    using namespace std;    
    struct Data {
        int ls,rs,l,r; 
    }t[maxn];                                  
    queue<int>Q;  
    int n,q,s,rtin,rtout,cnt,edges; 
    int hd[maxn],to[maxn],nex[maxn];  
    ll val[maxn],dis[maxn];   
    int inq[maxn];      
    void addedge(int u,int v,ll c) {     
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;       
    }
    int newnode() {
        return ++cnt;   
    }
    namespace In {
        void build(int l,int r,int &now) {
            if(l==r) {
                now=l;               
                return; 
            }  
            int mid=(l+r)>>1;    
            now=newnode(), t[now].l=l, t[now].r=r; 
            build(l,mid,lson), addedge(now,lson,0); 
            if(r>mid) build(mid+1,r,rson), addedge(now,rson,0);               
        } 
        void Add(int l,int r,int now,int L,int R,int c) {
            if(l>=L&&r<=R) {
                addedge(c,now,0); 
                return; 
            }
            int mid=(l+r)>>1;  
            if(L<=mid) Add(l,mid,lson,L,R,c); 
            if(R>mid) Add(mid+1,r,rson,L,R,c);      
        }
    }; 
    namespace Out {
        void build(int l,int r,int &now) {
            if(l==r) {
                now=l;               
                return; 
            }  
            int mid=(l+r)>>1;    
            now=newnode(), t[now].l=l, t[now].r=r;     
            build(l,mid,lson), addedge(lson,now,0); 
            if(r>mid) build(mid+1,r,rson), addedge(rson,now,0);               
        }
        void Add(int l,int r,int now,int L,int R,int c) {
            if(l>=L&&r<=R) {
                addedge(now,c,0); 
                return; 
            }
            int mid=(l+r)>>1;  
            if(L<=mid) Add(l,mid,lson,L,R,c); 
            if(R>mid) Add(mid+1,r,rson,L,R,c);      
        }
    };  
    void Addedge(int l1,int r1,int l2,int r2,ll delta) { 
        int p1=newnode(), p2=newnode(); 
        addedge(p1,p2,delta);    
        Out::Add(1,n,rtout,l1,r1,p1);   
        In::Add(1,n,rtin,l2,r2,p2);      
    }
    void spfa() {
        for(int i=0;i<maxn;++i) dis[i]=inf;   
        Q.push(s), dis[s]=0,inq[s]=1; 
        while(!Q.empty()) {
            int u=Q.front(); Q.pop(); 
            inq[u]=0;   
            for(int i=hd[u];i;i=nex[i]) {
                int v=to[i]; 
                if(dis[v] > dis[u]+val[i]) {
                    dis[v]=dis[u]+val[i];
                    if(!inq[v]) 
                        Q.push(v), inq[v]=1; 
                }
            }
        }
    }
    int main() {
        // setIO("input"); 
        scanf("%d%d%d",&n,&q,&s);   
        cnt=n, In::build(1,n,rtin), Out::build(1,n,rtout);    
        for(int i=1;i<=q;++i) {
            int opt,l1,r1,l2,r2,w;      
            scanf("%d",&opt);  
            if(opt==1) scanf("%d%d",&l1,&l2),r1=l1,r2=l2;   
            if(opt==2) scanf("%d%d%d",&l1,&l2,&r2),r1=l1; 
            if(opt==3) scanf("%d%d%d",&l2,&l1,&r1),r2=l2;            
            scanf("%d",&w);   
            Addedge(l1,r1,l2,r2,1ll*w);        
        }  
        spfa();    
        for(int i=1;i<=n;++i) printf("%I64d ",dis[i]==inf?-1:dis[i]);     
        return 0; 
    }
    

      

  • 相关阅读:
    BZOJ1045 [HAOI2008]糖果传递 && BZOJ3293 [Cqoi2011]分金币
    [BZOJ1103][POI2007]大都市meg dfs序+树状数组
    [BZOJ1122][POI2008]账本BBB 单调队列+后缀和
    [BZOJ1131][POI2008]Sta
    [BZOJ1370][Baltic2003]Gang团伙 并查集+拆点
    网易云基于 Kubernetes 的深度定制化实践
    微服务化的基石——持续集成
    微服务的接入层设计与动静资源隔离
    从互联网+角度看云计算的现状与未来(2)
    从互联网+角度看云计算的现状与未来(1)
  • 原文地址:https://www.cnblogs.com/guangheli/p/11226555.html
Copyright © 2011-2022 走看看