#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
char ch = getchar(); int x = 0, f = 1;
for(; !isdigit(ch) and ch != '-'; ch = getchar());
if(ch == '-') f = -1, ch = getchar();
for(; isdigit(ch); x = (x << 3) + (x << 1) + ch - 48, ch = getchar());
return x * f;
}
const int N = 1e5 + 5;
const int M = 3e5 + 5;
struct node{
int to, next, w, from;
}k[N << 3];
int head[N << 3], tot;
void add(int x, int y, int w){
k[++tot].from = x;
k[tot].to = y;
k[tot].w = w;
k[tot].next = head[x];
head[x] = tot;
}
void build(int cur, int l, int r){
// L[cur][0] = L[cur][1] = l;
// R[cur][0] = R[cur][1] = r;
if(l == r) return;
int mid = (l + r) >> 1;
add(cur, cur << 1, 0);
add(cur, cur << 1 | 1, 0);
add((cur << 1) + N, cur + N, 0);
add((cur << 1 | 1) + N, cur + N, 0);
build(cur << 1, l, mid);
build(cur << 1 | 1, mid + 1, r);
}
int find(int cur, int l, int r, int x){
if(l == r and r == x) return cur;
int mid = (l + r) >> 1;
if(x <= mid) return find(cur << 1, l, mid, x);
else return find(cur << 1 | 1, mid + 1, r, x);
}
void query(int cur, int l, int r, int x, int y, int end, int w){//点->区间
if(l >= x and r <= y){
add(end, cur, w);
return;
}
int mid = (l + r) >> 1;
if(x <= mid) query(cur << 1, l, mid, x, y, end, w);
if(y > mid) query(cur << 1| 1, mid + 1, r, x, y, end, w);
}
void query2(int cur, int l, int r, int x, int y, int end, int w){//区间->点
if(l >= x and r <= y){
add(cur + N, end, w);
return;
}
int mid = (l + r) >> 1;
if(x <= mid) query2(cur << 1, l, mid, x, y, end, w);
if(y > mid) query2(cur << 1 | 1, mid + 1, r, x, y, end, w);
}
struct use{
int id, x;
friend bool operator <(use x, use y){
return x.x > y.x;
}
};
int dis[N << 3];
bool vis[N << 3];
priority_queue<use>q;
void dijkstra(int x){
memset(dis, 0x3f, sizeof(dis)); dis[x] = 0;
q.push((use){x, 0});
memset(vis, 0, sizeof(vis));
while(!q.empty()){
use now = q.top(); q.pop();
if(vis[now.id] == true) continue;
vis[now.id] = true;
for(int i = head[now.id]; i; i = k[i].next){
if(dis[k[i].to] >= dis[now.id] + k[i].w){
//cout << "w" << "\n";
//cout << now.id << "------->" << k[i].to << "\n";
dis[k[i].to] = dis[now.id] + k[i].w;
q.push((use){k[i].to, dis[k[i].to]});
}
}
}
}
signed main(){
int n = read(), q = read(), s = read();
build(1, 1, n);
for(int i = 1; i <= n; i++){
int x = find(1, 1, n, i);
add(x, x + N, 0);
add(x + N, x, 0);
}
for(int i = 1; i <= q; i++){
int opt = read(), x = read(), l = read(), r = read(), w;
if(opt == 1) add(find(1, 1, n, x) + N, find(1, 1, n, l), r);
else if(opt == 2) {
w = read();
query(1, 1, n, l, r, find(1, 1, n, x) + N, w);
}
else if(opt == 3) {
w = read();
query2(1, 1, n, l, r, find(1, 1, n, x), w);
}
}
dijkstra(find(1, 1, n, s));
for(int i = 1; i <= n; i++){
int x = find(1, 1, n, i);
cout << (dis[x] == 0x3f3f3f3f3f3f3f3f ? (-1) : (dis[x])) << " ";
}
}
qwq