zoukankan      html  css  js  c++  java
  • 【CF786B】 Legacy

    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]]);
    	}
    }
    
  • 相关阅读:
    资料存储
    Django学习
    爬虫学习
    time()模块
    一些功能性小程序段
    装饰器
    函数的知识点(理解难点剖析)
    linux中的回收站机制,防止rm -rf 事件
    python--列表解析式 -- 知识整理
    python- 时间模块 datatime 知识整理
  • 原文地址:https://www.cnblogs.com/youddjxd/p/11622476.html
Copyright © 2011-2022 走看看