zoukankan      html  css  js  c++  java
  • [CodeForces]786B Legacy

    线段树优化建图。 建立两棵线段树,其上点的点权分别表示“到达这个区间内所有点的最小花费”和“到达这个区间内任意一个点的最小花费”。
    对于第一种路直接加边即可 对于第二种路,添加从v到第一棵线段树对应区间中的点的边 对于第三种路,添加从第二棵线段树对应区间中的点到v的边。
    可以给每个区间设一个序号,将对应区间与对应点连边就行了。之前一直没有YY出来这个,一直放的。。。

    #include <iostream>
    #include <queue>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=300005;
    struct Edge{int to,nxt,val;}e[2000005];
    int head[N],ecnt,cnt,ql,qr,opt,n,q,S,rt1,rt2;
    void add(int bg,int ed,int val) {e[++ecnt].nxt=head[bg];e[ecnt].to=ed;e[ecnt].val=val;head[bg]=ecnt;}
    int ls[N],rs[N];
    void build1(int &k,int l,int r) {
    	if(l<r) {
    		k=++cnt;int mid=l+r>>1;
    		build1(ls[k],l,mid);build1(rs[k],mid+1,r);
    		add(k,ls[k],0);add(k,rs[k],0);
    	}
    	else k=l;
    }
    void build2(int &k,int l,int r) {
    	if(l<r) {
    		k=++cnt;int mid=l+r>>1;
    		build2(ls[k],l,mid);build2(rs[k],mid+1,r);
    		add(ls[k],k,0);add(rs[k],k,0);
    	}
    	else k=l;
    }
    void update(int k,int l,int r,int u,int val) {
    	if(ql<=l&&r<=qr) {
    		opt==2?add(u,k,val):add(k,u,val);return;
    	}
    	int mid=l+r>>1;
    	if(ql<=mid) update(ls[k],l,mid,u,val);
    	if(mid<qr) update(rs[k],mid+1,r,u,val);
    }
    long long dis[N];
    struct Node {
    	int id;long long dis;
    	bool operator < (const Node &rhs) const {return dis>rhs.dis;}
    };
    void dij() {
    	priority_queue<Node>q; 
    	q.push({S,0});
    	memset(dis,0x3f,sizeof dis);
    	dis[S]=0;
    	while(!q.empty()) {
    		Node u=q.top();q.pop();
    		if(u.dis!=dis[u.id]) continue;
    		for(int i=head[u.id];i;i=e[i].nxt) {
    			int v=e[i].to;
    			if(dis[u.id]+e[i].val<dis[v]) {
    				dis[v]=dis[u.id]+e[i].val;q.push({v,dis[v]});
    			}
    		}
    	}
    }
    int main() {
    	scanf("%d%d%d",&n,&q,&S);
    	cnt=n;
    	build1(rt1,1,n);
    	build2(rt2,1,n);
    	int u,v,val;
    	while(q--) {
    		scanf("%d",&opt);
    		if(opt==1) {
    			scanf("%d%d%d",&u,&v,&val);add(u,v,val);
    		}
    		else {
    			scanf("%d%d%d%d",&u,&ql,&qr,&val);
    			update(opt==3?rt2:rt1,1,n,u,val);
    		}
    	}
    	dij();
    	for(int i=1;i<=n;i++) 
    		printf("%lld ",(dis[i]==0x3f3f3f3f3f3f3f3f)?-1:dis[i]);
    }
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    luogu P2852 [USACO06DEC]Milk Patterns G
    FZOJ 4267 树上统计
    CF1303G Sum of Prefix Sums
    luogu P5311 [Ynoi2011]成都七中
    luogu P5306 [COCI2019] Transport
    SP34096 DIVCNTK
    luogu P5325 【模板】Min_25筛
    luogu P1742 最小圆覆盖
    求两直线交点坐标
    1098: 复合函数求值(函数专题)
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9489618.html
Copyright © 2011-2022 走看看