ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[CF786B]Legacy

2019-10-04 16:54:31  阅读:203  来源: 互联网

标签:连边 head int edge add Legacy CF786B dis


Legacy

题目大意

维护一个图,可以随时:

1、加入一条边\((u,v)\)

2、加入一个边集\((u,{l~r})\)

3、加入一个边集\(({l~r},u)\)

以上的所有边都被设定了权值,最后求从某一点出发到所有点的最短路。

Solution

如果暴力建边+dij是会T的

那么我们考虑线段树优化建边

我们建立两棵线段树,一棵a,从儿子向父亲连边,另一棵b从父亲向儿子连边,然后b的叶子向a的对应叶子连边,统一都为0的权值

然后如果是单点向单点连边,就从a的叶子连向b的叶子连边

单点向区间连的话,就从a的儿子向b的区间连边

区间连向单点就是从a的区间向b的儿子连边

最后跑一遍dij就好了。

另外,SPFA会T

code:

#include<bits/stdc++.h>
using namespace std;
#define int long long
struct qwq{
    int v,w;
    int nxt;
}edge[4000010];
int cnt=-1;
int head[1000010];
void add(int u,int v,int w){
    edge[++cnt].nxt=head[u];
    edge[cnt].v=v;
    edge[cnt].w=w;
    head[u]=cnt;
}
int numa[1000010],numb[1000010];
int re1[1000010],re2[1000010];
int tot;
void builda(int o,int l,int r){
    numa[o]=++tot;
    if(l==r){
        re1[l]=tot;
        return;
    }
    int mid=(l+r)/2;
    builda(o*2,l,mid);
    builda(o*2+1,mid+1,r);
    add(numa[o*2],numa[o],0);
    add(numa[o*2+1],numa[o],0);
}
void buildb(int o,int l,int r){
    numb[o]=++tot;
    if(l==r){
        re2[l]=tot;
        add(re2[l],re1[l],0);
        return;
    }
    int mid=(l+r)/2;
    buildb(o*2,l,mid);
    buildb(o*2+1,mid+1,r);
    add(numb[o],numb[o*2],0);
    add(numb[o],numb[o*2+1],0);
}
void update1(int o,int l,int r,int L,int R,int v,int w){
    if(L<=l&&r<=R){
        add(numa[o],v,w);
        return;
    }
    int mid=(l+r)/2;
    if(L<=mid)update1(o*2,l,mid,L,R,v,w);
    if(mid<R)update1(o*2+1,mid+1,r,L,R,v,w);
}
void update2(int o,int l,int r,int L,int R,int v,int w){
    if(L<=l&&r<=R){
        add(v,numb[o],w);
        return;
    }
    int mid=(l+r)/2;
    if(L<=mid)update2(o*2,l,mid,L,R,v,w);
    if(mid<R)update2(o*2+1,mid+1,r,L,R,v,w);
}
int dis[1000010];
struct QAQ{
    int v,w;
    bool operator <(const QAQ& tmp)const{
        return w>tmp.w;
    }
};
void dijkstra(int s){
    for(int i=1;i<=1000000;++i)dis[i]=100000000000000000ll;
    dis[s]=0;
    priority_queue<QAQ> q;
    q.push((QAQ){s,0});
    while(!q.empty()){
        QAQ u=q.top();
        q.pop();
        int v=u.v,w=u.w;
        if(w!=dis[v])continue;
        for(int i=head[v];~i;i=edge[i].nxt){
            int tv=edge[i].v,tw=edge[i].w;
            if(dis[tv]>dis[v]+tw){
                dis[tv]=dis[v]+tw;
                q.push((QAQ){tv,dis[tv]});
            }
        }
    }
}
signed main(){
    memset(head,-1,sizeof(head));
    int n,q,s;
    scanf("%lld%lld%lld",&n,&q,&s);
    builda(1,1,n);
    buildb(1,1,n);
    for(int i=1;i<=q;++i){
        int opt;
        scanf("%d",&opt);
        if(opt==1){
            int u,v,w;
            scanf("%lld%lld%lld",&u,&v,&w);
            add(re1[u],re2[v],w);
        }
        else if(opt==2){
            int u,l,r,w;
            scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
            update2(1,1,n,l,r,re1[u],w);
        }
        else {
            int u,l,r,w;
            scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
            update1(1,1,n,l,r,re2[u],w);
        }
    }
    dijkstra(re1[s]);
    for(int i=1;i<=n;++i){
        printf("%lld ",dis[re1[i]]>10000000000000ll?-1:dis[re1[i]]);
    }
}

标签:连边,head,int,edge,add,Legacy,CF786B,dis
来源: https://www.cnblogs.com/youddjxd/p/11622476.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有