刚开始想了两个小时,打算把区间分块然后计算,但是这就很灵性了看了一个大佬的博客,侵删
#include<cstring> #include<iostream> #include<vector> #include<cstdio> #include<queue> #define maxn 302020 using namespace std; typedef long long ll; const ll INF = 10000000000000; int root1 = 0; int root2 = 0; struct Node { int p; ll len; Node(int a, ll b) :p(a), len(b) {} }; vector<Node>G[maxn]; void insert(int be, int en, ll len) { G[be].push_back(Node(en, len)); } ll dis[maxn]; int vis[maxn]; int num; int lc[maxn]; int rc[maxn]; int bult1(int &node, int be, int en) { if (be == en) { node = be; return 0; } node = ++num; int mid = (be + en) / 2; bult1(lc[node], be, mid); bult1(rc[node], mid + 1, en); insert(node, lc[node], 0); insert(node, rc[node], 0); return 0; } int bult2(int &node, int be, int en) { if (be == en) { node = be; return 0; } node = ++num; int mid = (be + en) / 2; bult2(lc[node], be, mid); bult2(rc[node], mid + 1, en); insert(lc[node], node, 0); insert(rc[node], node, 0); return 0; } int n, m, s; ll length; int LL, RR; int querry(int node, int be, int en, int op,int begin) { if (LL <= be && en <= RR) { if (op == 2) insert(begin, node, length); if (op == 3) insert(node, begin, length); return 0; } int mid = (be + en) / 2; if (LL <= mid) querry(lc[node], be, mid, op, begin); if (mid < RR) querry(rc[node], mid + 1, en, op, begin); return 0; } int dijstra(int be) { for (int i = 0; i < maxn -100; i++) { vis[i] = 0; dis[i] = INF; } queue<int>que; que.push(be); dis[be] = 0; while (!que.empty()) { int x = que.front(); que.pop(); vis[x] = 0; for (int i = 0; i < G[x].size(); i++) { int p = G[x][i].p; if (dis[p] > dis[x] + G[x][i].len) { dis[p] = dis[x] + G[x][i].len; if (!vis[p]) { vis[p] = 1; que.push(p); } } } } return 0; } int main() { int t; scanf("%d %d %d", &n, &m, &s); num = n+1; bult1(root1, 1, n); bult2(root2, 1, n); int be, en; for (int i = 0; i < m; i++) { scanf("%d", &t); if (t == 1) { scanf("%d %d %lld", &be, &en, &length); insert(be, en, length); } else { scanf("%d %d %d %lld", &be, &LL, &RR,&length); if (t == 2) querry(root1, 1, n, t, be); else querry(root2, 1, n, t, be); } } dijstra(s); for (int i = 1; i <= n; i++) { if (dis[i] == INF) printf("-1 "); else printf("%lld ", dis[i]); } return 0; }