이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
/**
_ _ __ _ _ _ _ _ _
|a ||t ||o d | |o |
| __ _| | _ | __| _ |
| __ |/_ | __ /__\ / _\|
**/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N_MAX = 100000;
const int M_MAX = 100000;
const int Q_MAX = 100000;
const int SILVER_MAX = 1000000000;
const int LOG2_N = 17;
int N, M, Q;
int edge_u[N_MAX + 2], edge_v[N_MAX + 2];
vector <int> adj[N_MAX + 2];
int cpt_edge[M_MAX + 2], cpt_silver[M_MAX + 2];
int qry_start[Q_MAX + 2], qry_finish[Q_MAX + 2];
int qry_gold[Q_MAX + 2]; ll qry_silver[Q_MAX + 2];
int parent[N_MAX + 2], depth[N_MAX + 2];;
int label[N_MAX + 2], max_label[N_MAX + 2];
int curr_label;
void dfs (int u) {
max_label[u] = label[u] = ++curr_label;
for (int v : adj[u]) {
if (v != parent[u]) {
parent[v] = u;
depth[v] = depth[u] + 1;
dfs(v);
max_label[u] = max(max_label[u], max_label[v]);
}
}
}
int ancestor[N_MAX + 2][LOG2_N];
int find_ancestor (int u, int k) {
for (int t = 0; t < LOG2_N; t++) {
if ((k >> t) & 1) {
u = ancestor[u][t];
}
}
return u;
}
int find_lca (int u, int v) {
if (depth[u] > depth[v]) {
u = find_ancestor(u, depth[u] - depth[v]);
}
if (depth[v] > depth[u]) {
v = find_ancestor(v, depth[v] - depth[u]);
}
if (u == v) {
return u;
}
for (int t = LOG2_N - 1; t >= 0; t--) {
if (ancestor[u][t] != ancestor[v][t]) {
u = ancestor[u][t];
v = ancestor[v][t];
}
}
return parent[u];
}
int lower[Q_MAX + 2], higher[Q_MAX + 2];
int mid[Q_MAX + 2]; ll sum[Q_MAX + 2]; int cnt[Q_MAX + 2];
int cpt_order[M_MAX + 2];
int qry_order[Q_MAX + 2];
ll Fenwick_sum[N_MAX + 2]; int Fenwick_cnt[N_MAX + 2];
void update (int pos, int val) {
for (int i = pos; i <= N; i += i & -i) {
Fenwick_sum[i] += val;
Fenwick_cnt[i] += (val > 0 ? +1 : -1);
}
}
void update (int l, int r, int val) {
update(l, +val); update(r + 1, -val);
}
pair <ll, int> query (int pos) {
ll sum = 0; int cnt = 0;
for (int i = pos; i >= 1; i -= i & -i) {
sum += Fenwick_sum[i];
cnt += Fenwick_cnt[i];
}
return make_pair(sum, cnt);
}
void step () {
iota(cpt_order + 1, cpt_order + M + 1, 1);
iota(qry_order + 1, qry_order + Q + 1, 1);
sort(cpt_order + 1, cpt_order + M + 1, [&] (const int &i, const int &j) {
return cpt_silver[i] < cpt_silver[j];
});
sort(qry_order + 1, qry_order + Q + 1, [&] (const int &i, const int &j) {
return qry_silver[i] < qry_silver[j];
});
fill(Fenwick_sum + 1, Fenwick_sum + N + 1, 0);
fill(Fenwick_cnt + 1, Fenwick_cnt + N + 1, 0);
for (int i = 1, j = 0; i <= Q && mid[qry_order[i]] != INT_MAX; i++) {
while (j + 1 <= M && cpt_silver[cpt_order[j + 1]] <= mid[qry_order[i]]) {
int e = cpt_edge[cpt_order[++j]];
update(label[edge_v[e]], max_label[edge_v[e]], cpt_silver[cpt_order[j]]);
}
int u = qry_start[qry_order[i]], v = qry_finish[qry_order[i]];
int lca = find_lca(u, v);
ll sum_u; int cnt_u; tie(sum_u, cnt_u) = query(label[u]);
ll sum_v; int cnt_v; tie(sum_v, cnt_v) = query(label[v]);
ll sum_lca; int cnt_lca; tie(sum_lca, cnt_lca) = query(label[lca]);
sum[qry_order[i]] = sum_u + sum_v - 2 * sum_lca;
cnt[qry_order[i]] = cnt_u + cnt_v - 2 * cnt_lca;
}
}
int main () {
ios_base::sync_with_stdio(false);
cin.tie(0);
cin >> N >> M >> Q;
for (int i = 1; i <= N - 1; i++) {
cin >> edge_u[i] >> edge_v[i];
adj[edge_u[i]].push_back(edge_v[i]);
adj[edge_v[i]].push_back(edge_u[i]);
}
dfs(1);
for (int u = 1; u <= N; u++) {
ancestor[u][0] = parent[u];
}
for (int t = 1; t < LOG2_N; t++) {
for (int u = 1; u <= N; u++) {
ancestor[u][t] = ancestor[ancestor[u][t - 1]][t - 1];
}
}
for (int i = 1; i <= N - 1; i++) {
if (edge_u[i] != parent[edge_v[i]]) {
swap(edge_u[i], edge_v[i]);
}
}
for (int i = 1; i <= M; i++) {
cin >> cpt_edge[i] >> cpt_silver[i];
}
for (int i = 1; i <= Q; i++) {
cin >> qry_start[i] >> qry_finish[i];
cin >> qry_gold[i] >> qry_silver[i];
lower[i] = 0; higher[i] = SILVER_MAX;
}
while (true) {
bool done = true;
for (int i = 1; i <= Q; i++) {
if (lower[i] < higher[i]) {
done = false;
mid[i] = (lower[i] + higher[i] + 1) / 2;
cnt[i] = 0;
} else {
mid[i] = INT_MAX; // done
}
}
if (done == true) {
break;
}
step();
for (int i = 1; i <= Q; i++) {
if (mid[i] != INT_MAX) {
if (sum[i] <= qry_silver[i]) {
lower[i] = mid[i];
} else {
higher[i] = mid[i] - 1;
}
}
}
}
for (int i = 1; i <= Q; i++) {
mid[i] = lower[i];
}
step();
fill(Fenwick_sum + 1, Fenwick_sum + N + 1, 0);
fill(Fenwick_cnt + 1, Fenwick_cnt + N + 1, 0);
for (int i = 1; i <= M; i++) {
int e = cpt_edge[i];
update(label[edge_v[e]], max_label[edge_v[e]], cpt_silver[i]);
}
for (int i = 1; i <= Q; i++) {
int u = qry_start[i], v = qry_finish[i];
int lca = find_lca(u, v);
int total_cpt = query(label[u]).second + query(label[v]).second - 2 * query(label[lca]).second;
int with_silver = cnt[i];
if (with_silver < total_cpt) {
with_silver += min((ll) (total_cpt - with_silver), (qry_silver[i] - sum[i]) / (mid[i] + 1));
}
int with_gold = total_cpt - with_silver;
cout << (with_gold <= qry_gold[i] ? qry_gold[i] - with_gold : -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... |