제출 #796755

#제출 시각아이디문제언어결과실행 시간메모리
796755GusterGoose27Two Currencies (JOI23_currencies)C++17
100 / 100
626 ms133920 KiB
#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;
typedef long long ll;

const int MAXN = 1e5+5;
const int MAXB = 17;
int n, m, q;

vector<pii> edges[MAXN];
vector<int> at_edge[MAXN];
int cost[MAXN];
int pos[MAXN];
int lca[MAXN][MAXB];
int depth[MAXN];

class stree {
public:
	int lp, rp;
	stree *l = nullptr;
	stree *r = nullptr;
	ll sum = 0;
	int num = 0;
	stree(int lv, int rv) {
		lp = lv;
		rp = rv;
		if (lp < rp) {
			int mid = (lp+rp)/2;
			l = new stree(lp, mid);
			r = new stree(mid+1, rp);
		}
	}
	stree(stree *prev, int v) {
		assert(!prev->l);
		sum = prev->sum+v;
		num = prev->num+1;
		lp = prev->lp;
		rp = prev->rp;
	}
	stree(stree *l, stree *r) : l(l), r(r) {
		sum = l->sum+r->sum;
		num = l->num+r->num;
		lp = l->lp;
		rp = r->rp;
	}
	stree *upd(int p, int v) {
		if (lp > p || rp < p) return this;
		if (lp == rp) return new stree(this, v);
		return new stree(l->upd(p, v), r->upd(p, v));
	}
};

stree *trees[MAXN];

void dfs(int cur, int p = -1) {
	for (pii e: edges[cur]) {
		int nxt = e.first;
		if (nxt == p) continue;
		trees[nxt] = trees[cur];
		for (int v: at_edge[e.second]) {
			trees[nxt] = trees[nxt]->upd(pos[v], cost[v]);
		}
		lca[nxt][0] = cur;
		depth[nxt] = 1+depth[cur];
		dfs(nxt, cur);
	}
}

int get_lca(int s, int t) {
	if (depth[s] < depth[t]) swap(s, t);
	for (int i = MAXB-1; i >= 0 && depth[s] > depth[t]; i--) {
		if ((1<<i) <= depth[s]-depth[t]) s = lca[s][i];
	}
	if (s == t) return s;
	for (int i = MAXB-1; i >= 0; i--) {
		if (lca[s][i] != lca[t][i]) {
			s = lca[s][i];
			t = lca[t][i];
		}
	}
	assert(s != t);
	assert(lca[s][0] == lca[t][0]);
	return lca[s][0];
}

int walk(stree *a, stree *b, stree *c, ll &amt) { // return max num you can buy with this amt
	if (amt == 0) return 0;
	if (a->sum+b->sum-2*c->sum <= amt) {
		amt -= (a->sum+b->sum-2*c->sum);
		return (a->num+b->num-2*c->num);
	}
	else if (!a->l) {
		amt = 0;
		return 0;
	}
	int v = walk(a->l, b->l, c->l, amt);
	return v + walk(a->r, b->r, c->r, amt);
}

int main() {
	ios_base::sync_with_stdio(false); cin.tie(NULL);
	cin >> n >> m >> q;
	for (int i = 0; i < n-1; i++) {
		int x, y; cin >> x >> y; x--; y--;
		edges[x].push_back(pii(y, i));
		edges[y].push_back(pii(x, i));
	}
	vector<pii> sortable;
	for (int i = 0; i < m; i++) {
		int p, w; cin >> p >> w;
		p--;
		at_edge[p].push_back(i);
		cost[i] = w;
		sortable.push_back(pii(w, i));
	}
	sort(sortable.begin(), sortable.end());
	for (int i = 0; i < m; i++) pos[sortable[i].second] = i;
	trees[0] = new stree(0, m-1);
	dfs(0);
	for (int j = 1; j < MAXB; j++) {
		for (int i = 0; i < n; i++) lca[i][j] = lca[lca[i][j-1]][j-1];
	}
	for (int i = 0; i < q; i++) {
		int s, t, x; ll y; cin >> s >> t >> x >> y;
		s--; t--;
		int l = get_lca(s, t);
		int rem = trees[s]->num+trees[t]->num-2*trees[l]->num-walk(trees[s], trees[t], trees[l], y);
		if (rem <= x) cout << x-rem << '\n';
		else cout << "-1\n";
	}
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...