제출 #918445

#제출 시각아이디문제언어결과실행 시간메모리
918445OAleksaTwo Currencies (JOI23_currencies)C++14
100 / 100
3713 ms161716 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define f first
#define s second
const int N = 2e5 + 69;
const int C = 1e9 + 69;
const int K = 18;
const int inf = 1e18;
int up[N][K];
int n, m, q, p[N], c[N], par[N], timer, tin[N], tout[N];
int root[N], lc[30 * N], rc[30 * N], node, vis[N];
int st[30 * N], cnt[30 * N];
vector<int> g[N];
vector<pair<int, int>> e;
map<pair<int, int>, vector<int>> edges;
void Modify(int v, int rt, int tl, int tr, int p) {
	if (tl == tr) {
		cnt[v] = cnt[rt] + 1;
		st[v] = st[rt] + tl;
	}
	else {
		int mid = (tl + tr) / 2;
		if (p <= mid) {
			lc[v] = ++node;
			rc[v] = rc[rt];
			Modify(lc[v], lc[rt], tl, mid, p);
		}
		else {
			rc[v] = ++node;
			lc[v] = lc[rt];
			Modify(rc[v], rc[rt], mid + 1, tr, p);
		}
		st[v] = st[lc[v]] + st[rc[v]];
		cnt[v] = cnt[lc[v]] + cnt[rc[v]];
	}
}
int GetSum(int v, int v1, int v2, int tl, int tr, int l, int r) {
	if (tl > r || tr < l)
		return 0;
	else if (tl >= l && tr <= r)
		return st[v] + st[v1] - 2 * st[v2];
	else {
		int mid = (tl + tr) / 2;
		return GetSum(lc[v], lc[v1], lc[v2], tl, mid, l, r) + GetSum(rc[v], rc[v1], rc[v2], mid + 1, tr, l, r);
	}
}
int GetCnt(int v, int v1, int v2, int tl, int tr, int l, int r) {
	if (tl > r || tr < l)
		return 0;
	else if (tl >= l && tr <= r)
		return cnt[v] + cnt[v1] - 2 * cnt[v2];
	else {
		int mid = (tl + tr) / 2;
		return GetCnt(lc[v], lc[v1], lc[v2], tl, mid, l, r) + GetCnt(rc[v], rc[v1], rc[v2], mid + 1, tr, l, r);
	}
}
int Cnt(int v, int tl, int tr, int p) {
	if (tl == tr)
		return cnt[v];
	else {
		int mid = (tl + tr) / 2;
		if (p <= mid)
			return Cnt(lc[v], tl, mid, p);
		else
			return Cnt(rc[v], mid + 1, tr, p);
	}
}
bool anc(int a, int b) {
	return tin[a] <= tin[b] && tout[a] >= tout[b];
}
int lca(int a, int b) {
	if (anc(a, b))
		return a;
	else if (anc(b, a))
		return b;
	for (int i = K - 1;i >= 0;i--) {
		if (!anc(up[a][i], b) && up[a][i] > 0)
			a = up[a][i];
	}
	return up[a][0];
}
void dfs(int v, int p) {
	par[v] = p;
	tin[v] = ++timer;
	up[v][0] = p;
	root[v] = root[p];
	int x = v, y = p;
	if (x > y)
		swap(x, y);
	if (edges.count({x, y})) {
		for (auto u : edges[{x, y}]) {
			int nr = ++node;
			Modify(nr, root[v], 0, C, u);
			root[v] = nr;
		}
	}
	for (int i = 1;i < K;i++)
		up[v][i] = up[up[v][i - 1]][i - 1];
	for (auto u : g[v]) {
		if (u == p)
			continue;
		dfs(u, v);
	}
	tout[v] = timer;
}
signed main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  int tt = 1;
  //cin >> tt;
  while (tt--) {
  	cin >> n >> m >> q;
  	for (int i = 1;i <= n - 1;i++) {
  		int a, b;
  		cin >> a >> b;
  		g[a].push_back(b);
  		g[b].push_back(a);
  		e.push_back({a, b});
  	}
  	for (int i = 1;i <= m;i++) {
  		int p, x;
  		cin >> p >> x;
  		vis[p] = 1;
  		--p;
  		int a, b;
  		tie(a, b) = e[p];
  		if (a > b)
  			swap(a, b);
  		edges[{a, b}].push_back(x);
  	}
  	dfs(1, 0);
  	while (q--) {
  		int s, t, x, y;
  		cin >> s >> t >> x >> y;
  		int lc = lca(s, t);
  		int l = 0, r = C, ans = -1;
  		int uk = cnt[root[s]] + cnt[root[t]] - 2 * cnt[root[lc]];
  		auto Check = [&](int mid) {
  			int sum = GetSum(root[s], root[t], root[lc], 0, C, 0, mid);
  			int c = GetCnt(root[s], root[t], root[lc], 0, C, 0, mid);
  			return make_pair(sum, c);
  		};
  		while (l <= r) {
  			int mid = (l + r) / 2;
  			auto p = Check(mid);
  			if (p.f > y) {
  				int x = Cnt(root[s], 0, C, mid) + Cnt(root[t], 0, C, mid);
  				x -= 2 * Cnt(root[lc], 0, C, mid);
  				if (p.f - (x - 1) * mid <= y) {
  					int r = y - (p.f - x * mid);
  					p.s -= x;
  					p.s += r / mid;
  					p.f -= x * mid;
  					p.f += r / mid * mid;
  				}
  			}
  			if (p.f <= y) {
  				ans = p.s;
  				l = mid + 1;
  			} 
  			else
  				r = mid - 1;
  		}
  		if (uk - ans <= x)
  			ans = x - (uk - ans);
  		else
  			ans = -1;
  		cout << ans << '\n';
  	}
	}
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...