이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
// QuangBuiCP
// https://oj.vnoi.info/problem/euler_k
#include "bits/stdc++.h"
using namespace std;
#ifdef LOCAL
#include "local/debug.hpp"
#else
#define debug(...)
#endif // LOCAL
template <typename T>
struct Fenwick {
int n;
vector<T> tree;
Fenwick(int n_) : n(n_) {
tree.assign(n + 1, T());
}
void Add(int x, T val) {
assert(1 <= x && x <= n);
while (x <= n) {
tree[x] += val;
x += x & -x;
}
}
T Get(int x) {
T res = T();
while (x >= 1) {
res += tree[x];
x -= x & -x;
}
return res;
}
};
const int LOG = 18;
int main() {
#ifndef LOCAL
cin.tie(nullptr)->sync_with_stdio(false);
#endif // LOCAL
int n, station, citizen;
cin >> n >> station >> citizen;
vector<int> u(n - 1), v(n - 1);
for (int i = 0; i < n - 1; ++i) {
cin >> u[i] >> v[i];
u[i]--, v[i]--;
}
vector<int> pos(station), cost(station);
for (int i = 0; i < station; ++i) {
cin >> pos[i] >> cost[i];
pos[i]--;
}
vector<int> start(citizen), end(citizen), gold(citizen);
vector<int64_t> silver(citizen);
for (int i = 0; i < citizen; ++i) {
cin >> start[i] >> end[i] >> gold[i] >> silver[i];
start[i]--, end[i]--;
}
vector<vector<int>> edge(n);
for (int i = 0; i < n - 1; ++i) {
edge[u[i]].push_back(v[i]);
edge[v[i]].push_back(u[i]);
}
vector<int> par(n, -1), depth(n, 0);
vector<vector<int>> childs(n);
{
queue<int> qu;
qu.push(0);
while (!qu.empty()) {
int x = qu.front();
qu.pop();
for (int y : edge[x]) if (y != par[x]) {
par[y] = x;
childs[x].push_back(y);
depth[y] = depth[x] + 1;
qu.push(y);
}
}
}
for (int i = 0; i < n - 1; ++i) {
if (v[i] == par[u[i]]) {
swap(u[i], v[i]);
}
}
vector<vector<int>> lift(LOG, vector<int>(n, -1));
lift[0] = par;
for (int i = 0; i < LOG - 1; ++i) {
for (int j = 0; j < n; ++j) {
if (lift[i][j] != -1) {
lift[i + 1][j] = lift[i][lift[i][j]];
}
}
}
vector<int> lca(citizen); // LCA(start[i], end[i])
for (int i = 0; i < citizen; ++i) {
int x = start[i], y = end[i];
if (depth[x] < depth[y]) {
swap(x, y);
}
for (int j = 0; j < LOG; ++j) {
if ((depth[x] - depth[y]) >> j & 1) {
x = lift[j][x];
}
}
if (x == y) {
lca[i] = x;
continue;
}
for (int j = LOG - 1; j >= 0; --j) {
if (lift[j][x] != lift[j][y]) {
x = lift[j][x];
y = lift[j][y];
}
}
lca[i] = par[x];
}
vector<int> tin(n), tout(n);
{
int timer = 0;
auto Dfs = [&](auto&& self, int x) -> void {
if (x != 0) {
tin[x] = ++timer;
}
for (int y : childs[x]) {
self(self, y);
}
if (x != 0) {
tout[x] = ++timer;
}
};
Dfs(Dfs, 0);
tin[0] = -1;
}
vector<int> order(station);
iota(order.begin(), order.end(), 0);
sort(order.begin(), order.end(), [&pos, &cost](int i, int j) {
if (cost[i] == cost[j]) {
return pos[i] < pos[j];
}
return cost[i] < cost[j];
});
vector<int> L(citizen, 0), R(citizen, station);
vector<int> used(citizen);
vector<vector<int>> candidates(station + 1);
for (int step = 0; step < 18; ++step) {
for (int i = 0; i < citizen; ++i) {
if (L[i] > R[i]) {
continue;
}
candidates[(L[i] + R[i]) / 2].push_back(i);
}
Fenwick<int> f(n * 2);
Fenwick<int64_t> g(n * 2);
for (int i = 0; i < station; ++i) {
f.Add(tin[v[pos[i]]], 1);
f.Add(tout[v[pos[i]]], -1);
}
for (int mid = 0; mid <= station; ++mid) {
for (int who : candidates[mid]) {
int64_t sum = g.Get(tin[start[who]]) + g.Get(tin[end[who]])
- g.Get(tin[lca[who]]) * 2;
if (sum <= silver[who]) {
used[who] = f.Get(tin[start[who]]) + f.Get(tin[end[who]])
- f.Get(tin[lca[who]]) * 2;
L[who] = mid + 1;
} else {
R[who] = mid - 1;
}
}
if (mid < station) {
int node = pos[order[mid]];
int val = cost[order[mid]];
f.Add(tin[v[node]], -1);
f.Add(tout[v[node]], 1);
g.Add(tin[v[node]], val);
g.Add(tout[v[node]], -val);
}
candidates[mid].clear();
}
}
debug(lca);
for (int i = 0; i < citizen; ++i) {
cout << max(gold[i] - used[i], -1) << '\n';
}
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |