[题目链接]
https://codeforces.com/contest/787/problem/D
[算法]
线段树优化建边 , 然后用Dijkstra算法求单源最短路
时间复杂度 : O((N + M)logN)
[代码]
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 10; typedef long long ll; typedef long double ld; typedef unsigned long long ull; const ll inf = 1e15; struct node { int lc , rc; } a[MAXN * 10]; struct edge { int to , w , nxt; } e[MAXN << 4]; int tot , cnt , n , q , s; int head[MAXN * 10] , root[2]; bool visited[MAXN * 10]; ll dist[MAXN * 10]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int x , int y , int w) { ++cnt; e[cnt] = (edge){y , w , head[x]}; head[x] = cnt; } inline void buildA(int &now , int l , int r) { if (l == r) { now = l; return; } now = ++tot; int mid = (l + r) >> 1; buildA(a[now].lc , l , mid); buildA(a[now].rc , mid + 1 , r); addedge(now , a[now].lc , 0); addedge(now , a[now].rc , 0); } inline void buildB(int &now , int l , int r) { if (l == r) { now = l; return; } now = ++tot; int mid = (l + r) >> 1; buildB(a[now].lc , l , mid); buildB(a[now].rc , mid + 1 , r); addedge(a[now].lc , now , 0); addedge(a[now].rc , now , 0); } inline void updateA(int now , int l , int r , int ql , int qr , int u , int w) { if (l == ql && r == qr) { addedge(u , now , w); return; } int mid = (l + r) >> 1; if (mid >= qr) updateA(a[now].lc , l , mid , ql , qr , u , w); else if (mid + 1 <= ql) updateA(a[now].rc , mid + 1 , r , ql , qr , u , w); else { updateA(a[now].lc , l , mid , ql , mid , u , w); updateA(a[now].rc , mid + 1 , r , mid + 1 , qr , u , w); } } inline void updateB(int now , int l , int r , int ql , int qr , int u , int w) { if (l == ql && r == qr) { addedge(now , u , w); return; } int mid = (l + r) >> 1; if (mid >= qr) updateB(a[now].lc , l , mid , ql , qr , u , w); else if (mid + 1 <= ql) updateB(a[now].rc , mid + 1 , r , ql , qr , u , w); else { updateB(a[now].lc , l , mid , ql , mid , u , w); updateB(a[now].rc , mid + 1 , r , mid + 1 , qr , u , w); } } inline void dijkstra(int s) { priority_queue< pair<ll , ll> , vector< pair<ll , ll> > , greater< pair<ll , ll> > > q; dist[s] = 0; q.push(make_pair(0 , s)); while (!q.empty()) { int u = q.top().second; q.pop(); if (visited[u]) continue; visited[u] = true; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to , w = e[i].w; if (dist[u] + w < dist[v]) { dist[v] = dist[u] + w; q.push(make_pair(dist[v] , v)); } } } } int main() { read(n); read(q); read(s); tot = n; buildA(root[0] , 1 , n); buildB(root[1] , 1 , n); while (q--) { int type; read(type); if (type == 1) { int u , v , w; read(u); read(v); read(w); addedge(u , v , w); } if (type == 2) { int l , r , v , w; read(v); read(l); read(r); read(w); updateA(root[0] , 1 , n , l , r , v , w); } if (type == 3) { int l , r , v , w; read(v); read(l); read(r); read(w); updateB(root[1] , 1 , n , l , r , v , w); } } for (int i = 1; i <= tot; i++) dist[i] = inf; dijkstra(s); for (int i = 1; i <= n; i++) printf("%lld " , dist[i] == inf ? -1 : dist[i]); return 0; }