Submission #731771

#TimeUsernameProblemLanguageResultExecution timeMemory
731771jk410Two Currencies (JOI23_currencies)C++17
100 / 100
3037 ms36932 KiB
#include <bits/stdc++.h>
#define all(v) v.begin(),v.end()
#define pb push_back
#define ll long long
using namespace std;
struct segmentTree {
	vector<ll> tree;
	void init(int n) {
		tree.clear();
		tree.resize(1 << (int)ceil(log2(n)) + 1);
	}
	void update(int lx, int rx, ll v, int l, int r, int n) {
		if (r < lx || rx < l)
			return;
		if (lx <= l && r <= rx) {
			tree[n] += v;
			return;
		}
		int m = (l + r) >> 1;
		update(lx, rx, v, l, m, n << 1);
		update(lx, rx, v, m + 1, r, n << 1 | 1);
	}
	ll query(int x, int l, int r, int n) {
		if (r < x || x < l)
			return 0;
		if (l == r)
			return tree[n];
		int m = (l + r) >> 1;
		return query(x, l, m, n << 1) + query(x, m + 1, r, n << 1 | 1) + tree[n];
	}
};
struct query {
	int s, t;
	ll x, y;
};
int N, M, Q;
vector<int> Adj[100000];
pair<int, int> Edges[100000];
pair<ll, int> CP[100000];
query Queries[100000];
int In[100000], Out[100000];
int Par[17][100000];
int Depth[100000];
int QL[100000], QR[100000], QX[100000];
segmentTree ST;
ll Ans[100000];
int dfs(int v, int par, int cur) {
	In[v] = ++cur;
	for (int i : Adj[v]) {
		if (i != par)
			cur = dfs(i, v, cur);
	}
	return Out[In[v]] = cur;
}
int getLCA(int u, int v) {
	if (Depth[u] > Depth[v])
		swap(u, v);
	for (int i = 0, t = Depth[v] - Depth[u]; t; i++, t >>= 1) {
		if (t & 1)
			v = Par[i][v];
	}
	if (u == v)
		return u;
	for (int i = 16; i >= 0; i--) {
		if (Par[i][u] != Par[i][v]) {
			u = Par[i][u];
			v = Par[i][v];
		}
	}
	return Par[0][u];
}
ll pathQuery(int u, int v) {
	int lca = getLCA(u, v);
	return ST.query(u, 0, N - 1, 1) + ST.query(v, 0, N - 1, 1) - 2 * ST.query(lca, 0, N - 1, 1);
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> N >> M >> Q;
	for (int i = 0; i < N - 1; i++) {
		int a, b;
		cin >> a >> b;
		Edges[i] = { --a,--b };
		Adj[a].pb(b);
		Adj[b].pb(a);
	}
	for (int i = 0; i < M; i++) {
		int p;
		ll c;
		cin >> p >> c;
		CP[i] = { c,--p };
	}
	sort(CP, CP + M);
	for (int i = 0; i < Q; i++) {
		int s, t;
		ll x, y;
		cin >> s >> t >> x >> y;
		Queries[i] = { --s,--t,x,y };
	}
	dfs(0, -1, -1);
	for (int i = 0; i < N - 1; i++) {
		pair<int, int>& cur = Edges[i];
		cur.first = In[cur.first];
		cur.second = In[cur.second];
		if (cur.first > cur.second)
			swap(cur.first, cur.second);
		Par[0][cur.second] = cur.first;
	}
	for (int i = 1; i < N; i++)
		Depth[i] = Depth[Par[0][i]] + 1;
	for (int i = 0; i < Q; i++) {
		query& cur = Queries[i];
		cur.s = In[cur.s];
		cur.t = In[cur.t];
	}
	for (int i = 1; i < 17; i++) {
		for (int j = 0; j < N; j++)
			Par[i][j] = Par[i - 1][Par[i - 1][j]];
	}
	fill(QR, QR + Q, M);
	while (1) {
		bool flag = true;
		vector<pair<int, int>> v;
		for (int i = 0; i < Q; i++) {
			if (QL[i] <= QR[i]) {
				flag = false;
				v.pb({ (QL[i] + QR[i]) >> 1,i });
			}
		}
		if (flag)
			break;
		sort(all(v));
		ST.init(N);
		for (int i = 0, j = 0; i <= M; i++) {
			if (i) {
				int cur = Edges[CP[i - 1].second].second;
				ll c = CP[i - 1].first;
				ST.update(cur, Out[cur], c, 0, N - 1, 1);
			}
			while (j < (int)v.size() && v[j].first == i) {
				int cur = v[j++].second;
				if (pathQuery(Queries[cur].s, Queries[cur].t) <= Queries[cur].y) {
					QX[cur] = i;
					QL[cur] = i + 1;
				}
				else
					QR[cur] = i - 1;
			}
		}
	}
	vector<pair<int, int>> v;
	for (int i = 0; i < Q; i++)
		v.push_back({ QX[i],i });
	sort(all(v));
	ST.init(N);
	for (int i = 0, j = 0; i <= M; i++) {
		if (i) {
			int cur = Edges[CP[i - 1].second].second;
			ST.update(cur, Out[cur], 1, 0, N - 1, 1);
		}
		while (j < (int)v.size() && v[j].first == i) {
			int cur = v[j++].second;
			Ans[cur] = pathQuery(Queries[cur].s, Queries[cur].t);
		}
	}
	for (int i = 0; i < Q; i++)
		cout << max(Queries[i].x - pathQuery(Queries[i].s, Queries[i].t) + Ans[i], (ll)-1) << "\n";
	return 0;
}

Compilation message (stderr)

currencies.cpp: In member function 'void segmentTree::init(int)':
currencies.cpp:10:39: warning: suggest parentheses around '+' inside '<<' [-Wparentheses]
   10 |   tree.resize(1 << (int)ceil(log2(n)) + 1);
      |                    ~~~~~~~~~~~~~~~~~~~^~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...