题意:
实现如下连边后跑最短路。
思路:
优化建图板子题,优化思路就是将区间分割成若干个线段树上的线段,与线段树分治有点类似,由于有点向区间也有区间向点的边,那么我们需要建两颗线段树,点向区间的树是自顶向下连边,区间向点的是自底向上连边,最后两棵树的最后一层需要与原来的
n
n
n个点连双向(未经说明都是单向边),比如下面这个图(盗用了日报的图)
让后我们就按照图来建边就好啦,我这里第一颗编号是
[
1
,
4
∗
n
]
[1,4*n]
[1,4∗n],第二棵编号是
[
4
∗
n
+
1
,
8
∗
n
]
[4*n+1,8*n]
[4∗n+1,8∗n],绿色点是
[
8
∗
n
+
1
,
9
∗
n
]
[8*n+1,9*n]
[8∗n+1,9∗n]。
当然可以舍去绿色的点,直接以线段树叶子节点为绿色的点,下面也给出代码了,只需要记一下
l
e
a
f
[
i
]
leaf[i]
leaf[i]即可。
// Problem: B. Legacy
// Contest: Codeforces - Codeforces Round #406 (Div. 1)
// URL: https://codeforces.com/problemset/problem/786/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;
//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,int> PII;
const int N=900200,M=N*40,mod=1e9+7,INF=0x3f3f3f3f;
const LL inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-6;
int n,q,s,b1,b2;
int e[M],ne[M],w[M],h[N],idx;
LL dis[N];
bool st[N];
//第一颗线段树1-4*n 第二棵4*n+1-8*n 点8*n+1-9*n
void add(int a,int b,int c) {
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void build(int u,int l,int r) {
if(l==r) {
add(u,l+8*n,0); add(l+8*n,u,0);
add(u+4*n,l+8*n,0); add(l+8*n,u+4*n,0);
return;
}
add(u,u*2,0); add(u,u*2+1,0);
add(u*2+4*n,u+4*n,0); add(u*2+1+4*n,u+4*n,0);
int mid=(l+r)>>1;
build(u<<1,l,mid); build(u<<1|1,mid+1,r);
}
void change1(int u,int l,int r,int ql,int qr,int st,int cs) {
if(ql<=l&&qr>=r) {
add(st+8*n,u,cs);
return;
}
int mid=(l+r)>>1;
if(ql<=mid) change1(u<<1,l,mid,ql,qr,st,cs);
if(qr>mid) change1(u<<1|1,mid+1,r,ql,qr,st,cs);
}
void change2(int u,int l,int r,int ql,int qr,int st,int cs) {
if(ql<=l&&qr>=r) {
add(u+4*n,st+8*n,cs);
return;
}
int mid=(l+r)>>1;
if(ql<=mid) change2(u<<1,l,mid,ql,qr,st,cs);
if(qr>mid) change2(u<<1|1,mid+1,r,ql,qr,st,cs);
}
void dijkstra() {
priority_queue<PII,vector<PII>,greater<PII> >q; q.push({0ll,s+8*n});
memset(dis,0x3f3f3f3f,sizeof(dis));
dis[s+8*n]=0;
while(q.size()) {
PII u=q.top(); q.pop();
if(st[u.Y]) continue;
st[u.Y]=1;
for(int i=h[u.Y];~i;i=ne[i]) {
int j=e[i];
if(dis[j]>dis[u.Y]+w[i]) {
dis[j]=dis[u.Y]+w[i];
q.push({dis[j],j});
}
}
}
for(int i=1;i<=n;i++) printf("%lld ",dis[i+8*n]==inf? -1:dis[i+8*n]);
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
memset(h,-1,sizeof(h));
cin>>n>>q>>s;
build(1,1,n);
while(q--) {
int op,v,l,r,c;
scanf("%d",&op);
if(op==1) {
scanf("%d%d%d",&l,&r,&c);
add(l+8*n,r+8*n,c);
}
else if(op==2) {
scanf("%d%d%d%d",&v,&l,&r,&c);
change1(1,1,n,l,r,v,c);
}
else {
scanf("%d%d%d%d",&v,&l,&r,&c);
change2(1,1,n,l,r,v,c);
}
}
dijkstra();
return 0;
}
/*
*/
// Problem: B. Legacy
// Contest: Codeforces - Codeforces Round #406 (Div. 1)
// URL: https://codeforces.com/problemset/problem/786/B
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;
//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,int> PII;
const int N=800200,M=N*20,mod=1e9+7,INF=0x3f3f3f3f;
const LL inf=0x3f3f3f3f3f3f3f3f;
const double eps=1e-6;
int n,q,s,b1,b2;
int e[M],ne[M],w[M],h[N],idx;
int leaf[N];
LL dis[N];
bool st[N];
//第一颗线段树1-4*n 第二棵4*n+1-8*n
void add(int a,int b,int c) {
e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}
void build(int u,int l,int r) {
if(l==r) {
leaf[l]=u;
return;
}
int mid=(l+r)>>1;
add(u,u*2,0); add(u,u*2+1,0);
add(u*2+4*n,u+4*n,0); add(u*2+1+4*n,u+4*n,0);
build(u<<1,l,mid); build(u<<1|1,mid+1,r);
}
void change1(int u,int l,int r,int ql,int qr,int st,int w) {
if(ql<=l&&qr>=r) {
add(st,u,w);
return;
}
int mid=(l+r)>>1;
if(ql<=mid) change1(u<<1,l,mid,ql,qr,st,w);
if(qr>mid) change1(u<<1|1,mid+1,r,ql,qr,st,w);
}
void change2(int u,int l,int r,int ql,int qr,int st,int w) {
if(ql<=l&&qr>=r) {
add(u+4*n,st,w);
return;
}
int mid=(l+r)>>1;
if(ql<=mid) change2(u<<1,l,mid,ql,qr,st,w);
if(qr>mid) change2(u<<1|1,mid+1,r,ql,qr,st,w);
}
void dijkstra() {
memset(dis,0x3f3f3f3f,sizeof(dis));
priority_queue<PII,vector<PII>,greater<PII>>q;
q.push({s,leaf[s]}); dis[leaf[s]]=0;
while(q.size()) {
PII u=q.top(); q.pop();
if(st[u.Y]) continue;
st[u.Y]=1;
for(int i=h[u.Y];~i;i=ne[i]) {
int j=e[i];
if(dis[j]>dis[u.Y]+w[i]) {
dis[j]=dis[u.Y]+w[i];
q.push({dis[j],j});
}
}
}
for(int i=1;i<=n;i++) printf("%lld ",dis[leaf[i]]==inf? -1:dis[leaf[i]]);
}
int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
memset(h,-1,sizeof(h));
cin>>n>>q>>s;
build(1,1,n);
for(int i=1;i<=n;i++) add(leaf[i],leaf[i]+4*n,0),add(leaf[i]+4*n,leaf[i],0);
while(q--) {
int op,v,l,r,c;
scanf("%d",&op);
if(op==1) {
scanf("%d%d%d",&l,&r,&c);
add(leaf[l],leaf[r],c);
}
else if(op==2) {
scanf("%d%d%d%d",&v,&l,&r,&c);
change1(1,1,n,l,r,leaf[v],c);
}
else {
scanf("%d%d%d%d",&v,&l,&r,&c);
change2(1,1,n,l,r,leaf[v],c);
}
}
dijkstra();
return 0;
}
/*
*/