#include <bits/stdc++.h>
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define compact(v) v.erase(unique(all(v)), v.end())
#define dbg(v) "[" #v " = " << (v) << "]"
#define el "\n"
using namespace std;
typedef long long ll;
typedef long double ld;
mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
long long randRange(long long l, long long r){ return uniform_int_distribution<long long>(l,r)(rng); }
const int N = 2e5 + 5;
const int LOG = 20;
int n, m, q;
vector <int> adj[N];
int p[N], c[N];
pair<int, int> tmp[N];
int L[N], R[N], ANS[N];
struct edge {
int u, v;
ll cost;
edge(int u = 0, int v = 0, ll cost = 0) : u(u), v(v), cost(cost) {}
bool operator < (const edge& o) const {
return cost < o.cost;
}
};
edge edges[N];
int lft[N][LOG + 5], chain_id[N], head_chain[N], high[N], tin[N], tout[N], sz[N], timer = 0, cur_chain = 0;
struct BIT {
vector <ll> bit;
int n;
BIT(int n = 0) : n(n), bit(n + 5, 0) {}
void update(int pos, ll val) {
while(pos <= n) {
bit[pos] += val;
pos += pos & -pos;
}
}
void upd(int l, int r, ll val) {
if (l > r) return;
update(r, val);
}
ll get(int pos) {
ll res = 0;
while(pos) {
res += bit[pos];
pos -= pos & -pos;
}
return res;
}
ll query(int l, int r) {
return get(r) - get(l - 1);
}
void reset() {
for(int i = 0; i <= n; ++i)
bit[i] = 0;
}
};
void dfs_lca(int u) {
sz[u] = 1;
for(int v : adj[u]) {
if (v == lft[u][0]) continue;
high[v] = high[u] + 1;
lft[v][0] = u;
dfs_lca(v);
sz[u] += sz[v];
}
}
namespace LCA {
void prepare_lca() {
dfs_lca(1);
high[0] = -1;
for(int j = 1; j <= LOG; ++j) {
for(int i = 1; i <= n; ++i) {
lft[i][j] = lft[lft[i][j - 1]][j - 1];
}
}
}
int get_lca(int u, int v) {
if (high[u] < high[v])
swap(u, v);
int k = high[u] - high[v];
for(int i = 0; (1 << i) <= k; ++i) {
if (k >> i & 1) {
u = lft[u][i];
}
}
if (u == v) return u;
for(int i = LOG; i >= 0; --i) {
if (lft[u][i] != lft[v][i]) {
u = lft[u][i];
v = lft[v][i];
}
}
return lft[u][0];
}
} using namespace LCA;
void build_hld(int u, int par) {
if (head_chain[cur_chain] == 0) {
head_chain[cur_chain] = u;
}
chain_id[u] = cur_chain;
tin[u] = ++timer;
int fat = -1;
for(int v : adj[u]) {
if (v == par) continue;
if (fat == -1 || sz[fat] < sz[v]) {
fat = v;
}
}
if (fat != -1)
build_hld(fat, u);
for(int v : adj[u]) {
if (v == par || v == fat) continue;
++cur_chain;
build_hld(v, u);
}
tout[u] = timer;
}
void prepare_hld() {
prepare_lca();
build_hld(1, -1);
}
struct HLD {
BIT ft;
int n;
HLD(int n = 0) : n(n), ft(BIT(n)) {}
ll query_hld(int u, int v) {
int lca = get_lca(u, v);
ll res = 0;
while(chain_id[u] != chain_id[lca]) {
res += ft.query(tin[head_chain[chain_id[u]]], tin[u]);
u = lft[head_chain[chain_id[u]]][0];
}
while(chain_id[v] != chain_id[lca]) {
res += ft.query(tin[head_chain[chain_id[v]]], tin[v]);
v = lft[head_chain[chain_id[v]]][0];
}
if (high[u] < high[v]) res += ft.query(tin[u] + 1, tin[v]);
else res += ft.query(tin[v] + 1, tin[u]);
return res;
}
void update_hld(int u, int v, ll val) {
int lca = get_lca(u, v);
// cerr << u << " " << " " << v << el;
// cerr << lca << el;
// cerr << "_____________________" << el;
while(chain_id[u] != chain_id[lca]) {
ft.upd(tin[head_chain[chain_id[u]]], tin[u], val);
// cerr << "%%%" << el;
// cerr << head_chain[chain_id[u]] << " " << u << el;
// cerr << tin[head_chain[chain_id[u]]] << " " << tin[u] << el;
// cerr << "%%%" << el;
u = lft[head_chain[chain_id[u]]][0];
}
while(chain_id[v] != chain_id[lca]) {
ft.upd(tin[head_chain[chain_id[v]]], tin[v], val);
// cerr << "%%%" << el;
// cerr << head_chain[chain_id[v]] << " " << v << el;
// cerr << tin[head_chain[chain_id[v]]] << " " << tin[v] << el;
// cerr << "%%%" << el;
v = lft[head_chain[chain_id[v]]][0];
}
// cerr << "LAST: " << el;
// cerr << high[u] << " " << high[v] << el;
// cerr << query_hld(1, 10) << el;
if (high[u] < high[v]) ft.upd(tin[u] + 1, tin[v], val);
else ft.upd(tin[v] + 1, tin[u], val);
}
void reset() {
ft.reset();
}
};
struct query {
int s, t, x, id;
ll y;
query(int s = 0, int t = 0, int x = 0, ll y = 0, int id = 0) : s(s), t(t), x(x), y(y), id(id) {}
} eq[N];
vector <int> queries[N];
void solve() {
cin >> n >> m >> q;
for(int i = 1; i < n; ++i) {
int u, v; cin >> u >> v;
adj[u].eb(v);
adj[v].eb(u);
tmp[i] = {u, v};
}
for(int i = 1; i <= m; ++i) {
cin >> p[i] >> c[i];
edges[i] = edge(tmp[p[i]].first, tmp[p[i]].second, c[i]);
}
sort(edges + 1, edges + 1 + m);
for(int i = 1; i <= q; ++i) {
cin >> eq[i].s >> eq[i].t >> eq[i].x >> eq[i].y;
eq[i].id = i;
}
for(int i = 1; i <= q; ++i) {
L[i] = 0;
R[i] = m;
ANS[i] = -1;
}
prepare_hld();
HLD hld1(n), hld2(n);
// for(int i = 1; i <= m; ++i) {
// cerr << edges[i].u << " " << edges[i].v << " " << edges[i].cost << el;
// }
// cerr << el;
// hld1.update_hld(edges[1].u, edges[1].v, edges[1].cost);
while(true) {
bool finished = true;
for(int i = 1; i <= q; ++i) {
if (L[i] <= R[i]) {
queries[(L[i] + R[i]) >> 1].push_back(i);
finished = false;
}
}
if (finished == true) break;
for(int i = 1; i <= m; ++i) {
hld2.update_hld(edges[i].u, edges[i].v, 1);
}
for(int mid = 0; mid <= m; ++mid) {
if (mid > 0) {
hld1.update_hld(edges[mid].u, edges[mid].v, edges[mid].cost);
hld2.update_hld(edges[mid].u, edges[mid].v, -1);
}
for(auto _ : queries[mid]) {
int s = eq[_].s;
int t = eq[_].t;
int x = eq[_].x;
ll y = eq[_].y;
int id = eq[_].id;
ll silver = hld1.query_hld(s, t);
int gold = hld2.query_hld(s, t);
if (silver <= y) {
ANS[id] = max(ANS[id], x - gold);
L[_] = mid + 1;
}
else {
R[_] = mid - 1;
}
}
queries[mid].clear();
}
hld1.reset();
hld2.reset();
}
for(int i = 1; i <= q; ++i) {
cout << ANS[i] << el;
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
#define task "task"
if(fopen(task".inp", "r")) {
freopen(task".inp", "r", stdin);
freopen(task".out", "w", stdout);
}
solve();
return 0;
}
/*
*/
Compilation message (stderr)
currencies.cpp: In function 'int main()':
currencies.cpp:320:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
320 | freopen(task".inp", "r", stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
currencies.cpp:321:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
321 | freopen(task".out", "w", stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
# | 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... |