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]," 
"[i==n]);
92     return 0;
93 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/6899358.html