Legacy
线段树优化建边,开两颗线段树:
对于线段树1,自顶向下连边。对于线段树2,自底向上连边。
然后对于op1我们直接连边即可。
对于op2(u -> [l, r] cost = w),这个操作在线段树1上完成即可。
对于op3([l, r] -> v cost = w),这个操作在线段树2上完成即可。
最后跑一遍Dijkstra最短路即可。
/* Author : lifehappy */ #include <bits/stdc++.h> #define mid (l + r >> 1) #define lson rt << 1, l, mid #define rson rt << 1 | 1, mid + 1, r #define ls rt << 1 #define rs rt << 1 | 1 using namespace std; typedef long long ll; const int N = 2e6 + 10; int n, m, s, tree1[N], tree2[N], tot; int head[N], to[N], nex[N], value[N], vis[N], cnt = 1; ll dis[N]; void add(int x, int y, int w) { to[cnt] = y; nex[cnt] = head[x]; value[cnt] = w; head[x] = cnt++; } int build1(int rt, int l, int r) { if(l == r) { return tree1[rt] = l; } tree1[rt] = ++tot; int lid = build1(lson); int rid = build1(rson); add(tree1[rt], lid, 0); add(tree1[rt], rid, 0); return tree1[rt]; } int build2(int rt, int l, int r) { if(l == r) { return tree2[rt] = l; } tree2[rt] = ++tot; int lid = build2(lson); int rid = build2(rson); add(lid, tree2[rt], 0); add(rid, tree2[rt], 0); return tree2[rt]; } void add1(int rt, int l, int r, int u, int L, int R, int w) { if(l >= L && r <= R) { add(u, tree1[rt], w); return ; } if(L <= mid) add1(lson, u, L, R, w); if(R > mid) add1(rson, u, L, R, w); } void add2(int rt, int l, int r, int v, int L, int R, int w) { if(l >= L && r <= R) { add(tree2[rt], v, w); return ; } if(L <= mid) add2(lson, v, L, R, w); if(R > mid) add2(rson, v, L, R, w); } typedef pair<ll, int> pli; priority_queue<pli, vector<pli>, greater<pli> > q; void Dijkstra() { memset(dis, 0x3f, sizeof dis); dis[s] = 0; q.push(make_pair(0, s)); while(q.size()) { int temp = q.top().second; q.pop(); if(vis[temp]) continue; vis[temp] = 1; for(int i = head[temp]; i; i = nex[i]) { if(dis[to[i]] > dis[temp] + value[i]) { dis[to[i]] = dis[temp] + value[i]; q.push(make_pair(dis[to[i]], to[i])); } } } for(int i = 1; i <= n; i++) { printf("%lld%c", dis[i] == 0x3f3f3f3f3f3f3f3f ? -1 : dis[i], i == n ? '\n' : ' '); } } int main() { // freopen("in.txt", "r", stdin); // freopen("out.txt", "w", stdout); // ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); scanf("%d %d %d", &n, &m, &s); tot = n; build1(1, 1, n); build2(1, 1, n); for(int i = 1; i <= m; i++) { int op, x, y, l, r, w; scanf("%d", &op); if(op == 1) { scanf("%d %d %d", &x, &y, &w); add(x, y, w); } else if(op == 2) { scanf("%d %d %d %d", &x, &l, &r, &w);//x -> [l, r] cost w. add1(1, 1, n, x, l, r, w); } else { scanf("%d %d %d %d", &x, &l, &r, &w);//[l, r] -> x cost w. add2(1, 1, n, x, l, r, w); } } Dijkstra(); return 0; }