Submission #1312894

#TimeUsernameProblemLanguageResultExecution timeMemory
1312894orzorzorzConstruction of Highway (JOI18_construction)C++20
100 / 100
671 ms25540 KiB
#include <iostream> #include <vector> #include <algorithm> #include <set> using namespace std; typedef long long ll; const int MAXN = 100005; int N; ll C[MAXN]; vector<int> adj[MAXN]; int parent[MAXN], depth[MAXN], sz[MAXN], son[MAXN]; int top[MAXN], pos[MAXN], dfn_timer; // 1. 樹狀數組 (BIT) 用於計算逆序對 ll bit[MAXN]; void update(int i, int delta) { for (; i <= N; i += i & -i) bit[i] += delta; } ll query(int i) { ll s = 0; for (; i > 0; i -= i & -i) s += bit[i]; return s; } // 2. HLD 預處理 void dfs_sz(int u, int p, int d) { parent[u] = p; depth[u] = d; sz[u] = 1; for (int v : adj[u]) { dfs_sz(v, u, d + 1); sz[u] += sz[v]; if (sz[v] > sz[son[u]]) son[u] = v; } } void dfs_hld(int u, int t) { top[u] = t; pos[u] = ++dfn_timer; if (son[u]) dfs_hld(son[u], t); for (int v : adj[u]) { if (v != son[u]) dfs_hld(v, v); } } // 3. 管理顏色段的結構 struct Node { int l, r, val; bool operator<(const Node& other) const { return l < other.l; } }; set<Node> segments; // 拆分段 (珂朵莉樹技巧) auto split(int p) { auto it = segments.lower_bound({p, 0, 0}); if (it != segments.end() && it->l == p) return it; --it; int l = it->l, r = it->r, v = it->val; segments.erase(it); segments.insert({l, p - 1, v}); return segments.insert({p, r, v}).first; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> N; vector<ll> vals; for (int i = 1; i <= N; i++) { cin >> C[i]; vals.push_back(C[i]); } // 離散化 sort(vals.begin(), vals.end()); vals.erase(unique(vals.begin(), vals.end()), vals.end()); auto get_val = [&](ll x) { return lower_bound(vals.begin(), vals.end(), x) - vals.begin() + 1; }; vector<pair<int, int>> queries; for (int i = 0; i < N - 1; i++) { int u, v; cin >> u >> v; adj[u].push_back(v); queries.push_back({u, v}); } dfs_sz(1, 0, 1); dfs_hld(1, 1); // 初始化:每個城市一開始都是自己的初始值 for (int i = 1; i <= N; i++) { segments.insert({pos[i], pos[i], get_val(C[i])}); } for (auto& q : queries) { int u = q.first, b_val = get_val(C[q.second]); vector<pair<int, int>> path_segments; // {value, length} int curr = u; while (curr) { int l = pos[top[curr]], r = pos[curr]; auto it_r = split(r + 1); auto it_l = split(l); vector<Node> temp; for (auto it = it_l; it != it_r; ++it) temp.push_back(*it); // HLD 跳轉是從下往上,所以存入時要反轉順序 reverse(temp.begin(), temp.end()); for (auto& node : temp) { path_segments.push_back({node.val, node.r - node.l + 1}); } segments.erase(it_l, it_r); segments.insert({l, r, b_val}); curr = parent[top[curr]]; } // 計算逆序對:從根節點往葉子節點看 reverse(path_segments.begin(), path_segments.end()); ll cost = 0; ll total_count = 0; for (auto& seg : path_segments) { // 逆序對定義:s 在 t 前面且 val[s] > val[t] // 我們統計 BIT 中比當前值大的個數 cost += (ll)seg.second * (total_count - query(seg.first)); update(seg.first, seg.second); total_count += seg.second; } // 清理 BIT 以供下次使用 for (auto& seg : path_segments) update(seg.first, -seg.second); cout << cost << "\n"; } return 0; }

Compilation message (stderr)

construction.cpp: In function 'int main()':
construction.cpp:93:49: warning: narrowing conversion of 'get_val.main()::<lambda(ll)>(C[i])' from 'long int' to 'int' [-Wnarrowing]
   93 |         segments.insert({pos[i], pos[i], get_val(C[i])});
      |                                          ~~~~~~~^~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...