Codeforces Round #406 (Div. 2) D. Legacy
题目链接: Codeforces Round #406 (Div. 2) D. Legacy
题意:
n个点,m条边,起始点为s。一共有三种建边方式。
1:建立一条a->b权值为c的单向边、
2:建立一条v->[l,r]权值为d的单项边。
3:建立一条[l,r]->v权值为d的单项边。
求起点到各个点的最短距离。
题解:
显然直接建图会超时,看到区间,想到用线段树,最开始我想直接用线段树来模拟dij的优先队列。
发现好像不好写,然后考虑用增加辅助节点来实现区间更新。
比如 A可以到B,C,D,权值都为val,我们可以添加一个节点E,使E连接B,C,D,权值为0,然后A连向E,权值为val。
这样更新源点到E点的距离时,就相当于更新了B,C,D的距离,第三种情况同理。
最后建完图后跑一下最短路就行了。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define ls rt<<1 4 #define rs rt<<1|1 5 using namespace std; 6 typedef long long ll; 7 typedef pair<int,ll> P; 8 const int N=1e5+7; 9 ll inf=1ll<<62; 10 11 vector<P>g[N*5]; 12 int idx[2][N*4],ed,root[2]; 13 int n,q,s,inq[N*5]; 14 ll dis[N*5]; 15 inline void adg(int x,int y,int w){g[x].push_back(P(y,w));} 16 17 void build(int type,int &pos,int l=1,int r=n,int rt=1) 18 { 19 pos=++ed; 20 if(l==r) 21 { 22 if(!type)adg(pos,l,0); 23 else adg(l,pos,0); 24 return; 25 } 26 int mid=l+r>>1; 27 build(type,idx[type][ls],l,mid,ls); 28 build(type,idx[type][rs],mid+1,r,rs); 29 if(!type)adg(idx[type][rt],idx[type][ls],0),adg(idx[type][rt],idx[type][rs],0); 30 else adg(idx[type][ls],idx[type][rt],0),adg(idx[type][rs],idx[type][rt],0); 31 } 32 33 void update(int L,int R,int v,int val,int type,int l=1,int r=n,int rt=1) 34 { 35 if(L<=l&&r<=R) 36 { 37 if(!type)adg(v,idx[type][rt],val); 38 else adg(idx[type][rt],v,val); 39 return; 40 } 41 int mid=l+r>>1; 42 if(L<=mid)update(L,R,v,val,type,l,mid,ls); 43 if(R>mid)update(L,R,v,val,type,mid+1,r,rs); 44 } 45 46 void spfa() 47 { 48 int en,v,x; 49 queue<int>Q; 50 F(i,1,ed)dis[i]=inf; 51 dis[s]=0,Q.push(s); 52 while(!Q.empty()) 53 { 54 x=Q.front();Q.pop(); 55 inq[x]=0; 56 en=g[x].size()-1; 57 F(i,0,en)if(dis[v=g[x][i].first]>dis[x]+g[x][i].second) 58 { 59 dis[v]=dis[x]+g[x][i].second; 60 if(!inq[v])Q.push(v),inq[v]=1; 61 } 62 } 63 } 64 65 int main() 66 { 67 scanf("%d%d%d",&n,&q,&s); 68 ed=n; 69 build(0,root[0]),build(1,root[1]); 70 F(i,1,q) 71 { 72 int type,v,l,r,val; 73 scanf("%d",&type); 74 if(type==1) 75 { 76 scanf("%d%d%d",&v,&l,&val); 77 adg(v,l,val); 78 } 79 else if(type==2) 80 { 81 scanf("%d%d%d%d",&v,&l,&r,&val); 82 update(l,r,v,val,0); 83 } 84 else 85 { 86 scanf("%d%d%d%d",&v,&l,&r,&val); 87 update(l,r,v,val,1); 88 } 89 } 90 spfa(); 91 F(i,1,n)printf("%lld%c",dis[i]==inf?-1:dis[i]," \n"[i==n]); 92 return 0; 93 }