zoukankan      html  css  js  c++  java
  • Codeforces 787D Legacy 线段树 最短路

    题意:

    (n(1 leq n leq 10^5))个点,(q(1 leq q leq 10^5))条路和起点(s)

    路有三种类型:

    • 从点(v)到点(u)需要花费(w)
    • 从点(v)到区间([l,r])中的点花费为(w)
    • 从区间([l,r])中的点到点(v)花费为(w)

    求起点到各个点的最少花费

    分析:

    如下图,构建两颗线段树,边的花费都为(0)
    对于第一种路直接加边即可
    对于第二种路,添加从(v)到上面线段树对应区间中的点的边
    对于第三种路,添加从下面线段树对应区间中的点到(v)的边

    最后直接跑最短路

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <vector>
    #include <iostream>
    #include <string>
    #include <queue>
    using namespace std;
    #define REP(i, a, b) for(int i = a; i < b; i++)
    #define PER(i, a, b) for(int i = b - 1; i >= a; i--)
    #define SZ(a) ((int)a.size())
    #define MP make_pair
    #define PB push_back
    #define EB emplace_back
    #define ALL(a) a.begin(), a.end()
    typedef long long LL;
    typedef pair<LL, int> PII;
    
    const int maxn = 100000 + 10;
    
    int n, q, s;
    
    struct Edge {
    	int v, w, nxt;
    	Edge() {}
    	Edge(int v, int w, int nxt): v(v), w(w), nxt(nxt) {}
    };
    
    int ecnt, head[maxn * 9];
    Edge edges[maxn * 36];
    
    void AddEdge(int u, int v, int w) {
    	printf("%d->%d, w = %d
    ", u, v, w);
    	edges[ecnt] = Edge(v, w, head[u]);
    	head[u] = ecnt++;
    }
    
    int tot, T[2][maxn << 2];
    void build(int t, int o, int L, int R) {
    	T[t][o] = ++tot;
    	if(L == R) {
    		if(0 == t) AddEdge(T[t][o], L, 0);
    		else AddEdge(L, T[t][o], 0);
    		return;
    	}
    	int M = (L + R) / 2;
    	build(t, o<<1, L, M);
    	build(t, o<<1|1, M+1, R);
    	if(0 == t) {
    		AddEdge(T[t][o], T[t][o<<1], 0);
    		AddEdge(T[t][o], T[t][o<<1|1], 0);
    	} else {
    		AddEdge(T[t][o<<1], T[t][o], 0);
    		AddEdge(T[t][o<<1|1], T[t][o], 0);
    	}
    }
    
    int type, v, qL, qR, w;
    
    void update(int o, int L, int R) {
    	if(qL <= L && R <= qR) {
    		if(0 == type) AddEdge(v, T[type][o], w);
    		else AddEdge(T[type][o], v, w);
    		return;
    	}
    	int M = (L + R) / 2;
    	if(qL <= M) update(o<<1, L, M);
    	if(qR > M) update(o<<1|1, M+1, R);
    }
    
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    bool vis[maxn * 9];
    LL d[maxn * 9];
    
    priority_queue<PII, vector<PII>, greater<PII> > Q;
    void dijkstra() {
    	memset(d, 0x3f, sizeof(d));
    	d[s] = 0;
    	Q.emplace(0, s);
    	while(!Q.empty()) {
    		PII t = Q.top(); Q.pop();
    		int& u = t.second;
    		if(vis[u]) continue;
    		vis[u] = true;
    		for(int i = head[u]; ~i; i = edges[i].nxt) {
    			int& v = edges[i].v;
    			int& w = edges[i].w;
    			if(d[v] > d[u] + w) {
    				d[v] = d[u] + w;
    				Q.emplace(d[v], v);
    			}
    		}
    	}
    }
    
    int main() {
    	scanf("%d%d%d", &n, &q, &s);
    	memset(head, -1, sizeof(head));
    	tot = n;
    	REP(t, 0, 2) build(t, 1, 1, n);
    
    	while(q--) {
    		scanf("%d%d%d", &type, &v, &qL);
    		if(type == 1) {
    			scanf("%d", &w);
    			AddEdge(v, qL, w);
    		} else {
    			type -= 2;
    			scanf("%d%d", &qR, &w);
    			update(1, 1, n);
    		}
    	}
    
    	dijkstra();
    	REP(i, 1, n + 1) printf("%lld ", d[i] == INF ? -1 : d[i]);
    	printf("
    ");
    
    	return 0;
    }
    
  • 相关阅读:
    用shell脚本监控进程是否存在 不存在则启动的实例
    vue+element-ui+ajax实现一个表格的实例
    c的指针和php中的引用的区别
    mysql or条件查询优化
    Linq查询操作之投影操作
    Linq查询操作之Where筛选
    Linq专题之查询操作
    linq之join子句
    linq之let子句
    linq之into子句
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/6700795.html
Copyright © 2011-2022 走看看