【CF#786B】Legacy

  • 线段树优化建图的好题

题目翻译

有n的地点和m张机票,机票有三种:

第一种:可以从x到达y

第二种:可以由x到达区间[l,r]的地点

第三种:可以由区间[l,r]的地点到达x

机票的价格为w,种类用opt表示

问从S到达各个地点的最小花费

题解

看到区间,我们自然而然地想到线段树,但是由于考场上死磕C题而错过了这道题目。

我们用线段树优化建图,然后跑最短路即可。

注意:

  1. 线段树要建两颗,原因很显然。

  2. priority_queue默认是less,而这里用的是greater

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pii;
#define FILE "read"
#define MAXN (ll)2e6+10
struct node{ll y,next,v;}e[MAXN];
ll n,m,S,cnt,len,root[5],Link[MAXN],dis[MAXN],vis[MAXN],tr[MAXN][2];
priority_queue<pii,vector<pii >,greater<pii> > q;
//priority_queue<pii>q;
inline ll read(){
ll x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
void insert(ll x,ll y,ll v){e[++len].next=Link[x];Link[x]=len;e[len].y=y;e[len].v=v;}
void build(ll &p,ll l,ll r,ll opt){
if(l==r) {p=l; return;}
p=++cnt; ll mid=(l+r)>>1;
build(tr[p][0],l,mid,opt); build(tr[p][1],mid+1,r,opt);
if(!opt) insert(p,tr[p][0],0),insert(p,tr[p][1],0);
else insert(tr[p][0],p,0),insert(tr[p][1],p,0);
}
void updata(ll p,ll l,ll r,ll x,ll y,ll pos,ll v,ll opt){
if(x>r||y<l) return;
if(x<=l&&y>=r){
if(opt==2) insert(pos,p,v);
else insert(p,pos,v);
return;
}
ll mid=(l+r)>>1;
updata(tr[p][0],l,mid,x,y,pos,v,opt);
updata(tr[p][1],mid+1,r,x,y,pos,v,opt);
}
void dijkstra(){
memset(dis,10,sizeof(dis));
ll oo=dis[0]; dis[S]=0; vis[S]=1;
q.push(make_pair(dis[S],S));
while(!q.empty()){
ll v=q.top().first,x=q.top().second; q.pop();
//if(v>dis[x]) continue;
for(ll i=Link[x];i;i=e[i].next)if(dis[x]+e[i].v<dis[e[i].y]){
dis[e[i].y]=dis[x]+e[i].v;
if(!vis[e[i].y]) q.push(make_pair(dis[e[i].y],e[i].y));
}
vis[x]=0;
}
for(ll i=1;i<=n;++i){
if(dis[i]==oo) printf("-1 ");
else printf("%I64d ",dis[i]);
}
}
int main(){
//freopen(FILE".in","r",stdin);
//freopen(FILE".out","w",stdout);
n=cnt=read(); m=read(); S=read();
build(root[1],1,n,0); build(root[2],1,n,1);
for(ll i=1;i<=m;++i){
ll opt=read();
if(opt==1) {ll x=read(),y=read(),v=read();insert(x,y,v);}
else {ll x=read(),l=read(),r=read(),v=read();updata(root[opt-1],1,n,l,r,x,v,opt);}
}
dijkstra();
return 0;
}
文章目录
  1. 1. 题目翻译
  2. 2. 题解
,