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;
}