这个题目和之前写的一个线段树优化建图是一样的。
B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路
之前这个题目可以相当于一个模板,直接套用就可以了。
不过注意为了提高效率,在区间与区间之间建边的时候建了两个虚点。
#include <cstdio> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <string> #include <algorithm> #include <iostream> #include <map> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; typedef long long ll; const int maxn = 2e5 + 10; int numa[maxn * 4], numb[maxn * 4], lefta[maxn * 4], leftb[maxn * 4]; int start[maxn], endss[maxn]; ll d[maxn * 8], tot; int n, m, p, q; bool vis[maxn * 8]; struct edge { int from, to, dist; edge(int from = 0, int to = 0, int dist = 0) :from(from), to(to), dist(dist) {} }; struct heapnode { ll d; int u; heapnode(ll d = 0, int u = 0) : d(d), u(u) {} bool operator<(const heapnode &a) const { return a.d < d; } }; vector<edge> vec; vector<int> g[maxn * 8]; void add(int u, int v, int w) { vec.push_back(edge(u, v, w)); int m = vec.size(); g[u].push_back(m - 1); // printf("u=%d v=%d w=%d ", u, v, w); } void dijkstra() { priority_queue<heapnode>que; for (int i = 0; i <= tot; i++) d[i] = inf64; for(int i=1;i<=q;i++) { int id = lefta[start[i] + n]; d[id] = 0; que.push(heapnode(0, id)); } memset(vis, 0, sizeof(vis)); while (!que.empty()) { heapnode x = que.top(); que.pop(); int u = x.u; // printf("u=%d ", u); if (vis[u]) continue; vis[u] = 1; for (int i = 0; i < g[u].size(); i++) { edge &e = vec[g[u][i]]; // printf("u=%d e.to=%d e.dist=%d ", u, e.to, e.dist); // printf("d[%d]=%lld d[%d]=%lld ", u, d[u], e.to, d[e.to]); if (d[e.to] > d[u] + e.dist) { // printf("ww "); d[e.to] = d[u] + e.dist; // printf("d[%d]=%lld ", e.to, d[e.to]); que.push(heapnode(d[e.to], e.to)); } } // printf(" "); } } void builda(int id, int l, int r) { numa[id] = ++tot; int mid = (l + r) >> 1; if (l == r) { lefta[l] = tot; return; } builda(id << 1, l, mid); builda(id << 1 | 1, mid + 1, r); add(numa[id << 1], numa[id], 0); add(numa[id << 1 | 1], numa[id], 0); } void buildb(int id, int l, int r) { numb[id] = ++tot; int mid = (l + r) >> 1; if (l == r) { leftb[l] = tot; return; } buildb(id << 1, l, mid); buildb(id << 1 | 1, mid + 1, r); add(numb[id], numb[id << 1], 0); add(numb[id], numb[id << 1 | 1], 0); } void build3(int n) { for (int i = 1; i <= n; i++) add(leftb[i], lefta[i], 0); } void update(int id, int l, int r, int x, int y, vector<int>&d) { if (x <= l && y >= r) { d.push_back(id); return; } int mid = (l + r) >> 1; if (x <= mid) update(id << 1, l, mid, x, y, d); if (y > mid) update(id << 1 | 1, mid + 1, r, x, y, d); } vector<int>a, b; int main() { scanf("%d%d%d%d", &n, &m, &p, &q); builda(1, 1, 2 * n), buildb(1, 1, 2 * n), build3(2 * n); tot++; for (int i = 1; i <= m; i++) { int x1, y1, x2, y2, w; scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &w); a.clear(), b.clear(); update(1, 1, 2 * n, x1, y1, a); update(1, 1, 2 * n, x2 + n, y2 + n, b); int lena = a.size(), lenb = b.size(); for(int j=0;j<lena;j++) { int id = numa[a[j]]; add(id, tot, 0); } add(tot, tot + 1, w); for(int j=0;j<lenb;j++) { int id = numb[b[j]]; add(tot + 1, id, 0); } tot += 2; for(int j=0;j<lenb;j++) { int id = numa[b[j]]; add(id, tot, 0); } add(tot, tot + 1, w); for(int j=0;j<lena;j++) { int id = numb[a[j]]; add(tot + 1, id, 0); } tot += 2; } for (int i = 1; i <= p; i++) scanf("%d", &endss[i]); for (int i = 1; i <= q; i++) scanf("%d", &start[i]); dijkstra(); ll ans = 0; for(int i=1;i<=p;i++) { int id = lefta[endss[i]]; ans = max(ans, d[id]); } if (ans >= inf64) printf("boring game "); else printf("%lld ", ans); return 0; }