QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#109402 | #68. Designated Cities | bashkort | 0 | 0ms | 0kb | C++20 | 5.7kb | 2023-05-28 21:57:30 | 2023-05-28 21:57:32 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
namespace SegmentTree {
constexpr int N_ = 1 << 19;
pair<ll, int> t[N_];
int sz = 1;
void init(int n, vector<ll> dist) {
sz = 1 << __lg(n) + !!(n & (n - 1));
for (int i = 0; i < n; ++i) {
t[i + sz] = {dist[i], i};
}
for (int i = sz - 1; i > 0; --i) {
t[i] = max(t[i << 1], t[i << 1 | 1]);
}
}
void modify(int x) {
t[x += sz].first = 0;
while (x >>= 1) {
t[x] = max(t[x << 1], t[x << 1 | 1]);
}
}
pair<ll, int> rangeMax(int l, int r, int x = 1, int lx = 0, int rx = sz) {
if (l >= rx || lx >= r) {
return {};
}
if (l <= lx && rx <= r) {
return t[x];
}
int mid = lx + rx >> 1;
return max(rangeMax(l, r, x << 1, lx, mid), rangeMax(l, r, x << 1 | 1, mid, rx));
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<pair<int, int>>> adj(n);
vector<int> A(n), B(n), C(n), D(n);
for (int i = 0; i < n - 1; ++i) {
cin >> A[i] >> B[i] >> C[i] >> D[i];
--A[i], --B[i];
adj[A[i]].emplace_back(B[i], i);
adj[B[i]].emplace_back(A[i], i);
}
auto cost = [&](int to, int i) {
return B[i] == to ? C[i] : D[i];
};
vector<ll> ans(n + 1);
auto dij = [&](int source) -> vector<ll> {
vector<ll> dist(n, -1);
dist[source] = 0;
auto dfs = [&](auto self, int v) -> void {
for (auto [to, i] : adj[v]) {
if (dist[to] == -1) {
dist[to] = dist[v] + cost(to, i);
self(self, to);
}
}
};
dfs(dfs, source);
return dist;
};
vector<ll> dist0 = dij(0);
vector<ll> sub0(n), cost0(n);
ll wSum = 0;
for (int i = 0; i < n - 1; ++i) {
if (dist0[A[i]] < dist0[B[i]]) {
cost0[0] += D[i];
} else {
cost0[0] += C[i];
}
wSum += C[i];
wSum += D[i];
}
auto dfs1 = [&](auto self, int v, int par) -> void {
ans[1] = max(ans[1], cost0[v]);
for (auto [to, i] : adj[v]) {
if (to != par) {
cost0[to] = cost0[v] - cost(v, i) + cost(to, i);
self(self, to, v);
sub0[v] = sub0[v] + sub0[to] + cost(v, i);
}
}
};
dfs1(dfs1, 0, -1);
assert(cost0[0] == sub0[0]);
ans[n] = wSum; //to handle n = 2
vector<pair<ll, int>> dp(n);
ll diamDist = -1;
int dx = -1, dy = -1;
auto dfs0 = [&](auto self, int v, int par) -> void {
dp[v] = {dist0[v], v};
for (auto [to, i] : adj[v]) {
if (to != par) {
self(self, to, v);
if (dp[v].first + dp[to].first - 2 * dist0[v] + cost0[v] > diamDist) {
dx = dp[v].second;
dy = dp[to].second;
diamDist = dp[v].first + dp[to].first - 2 * dist0[v] + cost0[v];
}
dp[v] = max(dp[v], dp[to]);
}
}
};
dfs0(dfs0, 0, -1);
ans[2] = diamDist;
vector<int> tin(n), tout(n), ord(n), parent(n);
vector<ll> depth(n);
auto dfs = [&](auto self, int v, int par) -> void {
static int T = 0;
tin[v] = T++;
ord[tin[v]] = v;
for (auto [to, i] : adj[v]) {
if (to != par) {
parent[to] = v;
depth[to] = depth[v] + cost(to, i);
self(self, to, v);
}
}
tout[v] = T;
};
dfs(dfs, dx, -1);
vector<bool> used(n);
vector<ll> init(n);
for (int i = 0; i < n; ++i) {
init[i] = depth[ord[i]];
}
SegmentTree::init(n, init);
set<array<int, 3>> seg;
set<pair<ll, int>, greater<>> best;
map<pair<int, int>, pair<ll, int>> mp;
auto ins = [&](int l, int r, int v) {
if (l < r) {
seg.insert({l, r, v});
mp[{l, r}] = SegmentTree::rangeMax(l, r);
mp[{l, r}].first -= depth[v];
best.emplace(mp[{l, r}]);
}
};
auto er = [&](int l, int r, int v) {
if (l < r) {
seg.erase({l, r, v});
best.erase({mp[{l, r}]});
}
};
auto kill = [&](int v) {
int l = tin[v], r = tout[v];
auto it = seg.lower_bound({l + 1, -1});
if (it != seg.begin()) {
auto [lx, rx, x] = *prev(it);
er(lx, rx, x);
ins(lx, l, x), ins(r, rx, x);
}
ins(l, r, v);
};
auto choose = [&](int v) {
auto [l, r, x] = *prev(seg.lower_bound({tin[v] + 1, -1, -1}));
er(l, r, x);
SegmentTree::modify(tin[v]);
ins(l, r, x);
vector<int> t;
while (!used[v]) {
t.push_back(v);
v = parent[v];
}
while (!t.empty()) {
kill(t.back());
t.pop_back();
}
};
kill(dx);
choose(dy);
int k = 2;
ll sum = diamDist;
while (!best.empty()) {
auto [di, v] = *best.begin();
if (di <= 0) {
break;
}
k += 1;
sum += di;
ans[k] = sum;
choose(ord[v]);
}
for (int i = 1; i <= n; ++i) {
ans[i] = max(ans[i], ans[i - 1]);
}
int q;
cin >> q;
while (q--) {
int e;
cin >> e;
cout << wSum - ans[e] << '\n';
}
return 0;
}
详细
Subtask #1:
score: 0
Memory Limit Exceeded
Test #1:
score: 0
Memory Limit Exceeded
input:
2 1 2 781089648 283888890 2 1 2
output:
result:
Subtask #2:
score: 0
Memory Limit Exceeded
Test #12:
score: 0
Memory Limit Exceeded
input:
2 1 2 683402985 526289818 1 1
output:
result:
Subtask #3:
score: 0
Memory Limit Exceeded
Test #21:
score: 0
Memory Limit Exceeded
input:
2 2 1 92722556 873785501 1 2
output:
result:
Subtask #4:
score: 0
Skipped
Dependency #1:
0%
Subtask #5:
score: 0
Memory Limit Exceeded
Test #45:
score: 0
Memory Limit Exceeded
input:
2 1 2 543195986 144983073 1 1
output:
result:
Subtask #6:
score: 0
Skipped
Dependency #1:
0%