题目大意:
要求见一张图:
1、一个点连向另一个点,代价为 w w w
2、一个点连向一个区间,代价为 w w w
3、一个区间连向一个点,代价为 w w w
求连完点后,以以为初始节点,跑最短路,求初始节点到每一个节点的最短路
以上连边均是单向连边
先考虑朴素的算法,就是暴力连边,那么时间复杂度就是 O ( n 2 ) O(n^2) O(n2),直接超时了
这里要通过线段树要优化建图,这里要有一个知识点,内向树与外向树,
内向树如下:
所有线段树的节点都连向区间的内部,而且只允许外部连向内部,如图
以下的这种是错误的内向树,因为连向了外面
而外向树却恰恰相反,如图
而以下是错误的外向树
可以建两棵树一颗是内向树,另一颗是外向树,在建树的时候就把内向树,外向树的建好,然后就是连边,只要写成区间修改的形式就行了,也就是一个点连向一个区间就行了
当然需要动态开点,但叶子节点要和区间号一致,所以开点的时候就是要从 n + 1 开 始 n+1开始 n+1开始
连的时候注意下内向树,外向树就行了,另外还要注意 20 20 20倍空间
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
#define int long long
//#define double long double
#define re register int
#define void inline void
#define eps 1e-8
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
using namespace std;
const int mod=998244353;
const int M=1e9;
const int N=1e5+5;//?????????? 4e8
struct node
{
int ver,edge,next;
}e[N*20];
int tot,head[N*8];
int cnt,lc[N*8],rc[N*8];
int n,m,v[N*4];
ll d[N*4];
int rt1,rt2;
void add(int x,int y,int z)
{
e[++cnt].ver=y;
e[cnt].edge=z;
e[cnt].next=head[x];
head[x]=cnt;
}
void bulid1(int &p,int l,int r)
{
if(l==r)
{
p=l;
return;
}
p=++tot;
int mid=(l+r)>>1;
bulid1(lc[p],l,mid);bulid1(rc[p],mid+1,r);
add(p,lc[p],0);add(p,rc[p],0);
}
void bulid2(int &p,int l,int r)
{
if(l==r)
{
p=l;
return;
}
p=++tot;
int mid=(l+r)>>1;
bulid2(lc[p],l,mid);bulid2(rc[p],mid+1,r);
add(lc[p],p,0);add(rc[p],p,0);
}
void update(int p,int L,int R,int l,int r,int x,int z,int op)
{
if(L<=l&&r<=R)
{
if(op==2) add(x,p,z);
else add(p,x,z);
return;
}
int mid=(l+r)>>1;
if(L<=mid) update(lc[p],L,R,l,mid,x,z,op);
if(mid<R) update(rc[p],L,R,mid+1,r,x,z,op);
}
void dijkstra(int s)
{
priority_queue < P > q;
for(re i=0;i<N*4;i++) d[i]=1e18,v[i]=0;
d[s]=0;q.push(mk(0,s));
while(q.size())
{
int x=q.top().second;q.pop();
if(v[x]) continue;
v[x]=1;
for(re i=head[x];i;i=e[i].next)
{
int y=e[i].ver;
int z=e[i].edge;
if(d[y]>d[x]+z)
{
d[y]=d[x]+z;
q.push(mk(-d[y],y));
}
}
}
}
void solve()
{
int s;
cin>>n>>m>>s;
tot=n;
bulid1(rt1,1,n);bulid2(rt2,1,n);
while(m--)
{
int op,x,l,r,z;
scanf("%lld",&op);
if(op==1)
{
scanf("%lld%lld%lld",&l,&r,&z);
add(l,r,z);
}
else
{
scanf("%lld%lld%lld%lld",&x,&l,&r,&z);
update(op==2?rt1:rt2,l,r,1,n,x,z,op);
}
}
dijkstra(s);
for(re i=1;i<=n;i++) if(d[i]==1e18) d[i]=-1;
for(re i=1;i<=n;i++) printf("%lld ",d[i]);
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
// printf("Case %d:\n",index);
solve();
// puts("");
}
return 0;
}
/*
1
6
URLLDR
*/