This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define MASK(i) (1LL << (i))
#define GETBIT(mask, i) (((mask) >> (i)) & 1)
#define ALL(v) (v).begin(), (v).end()
ll max(ll a, ll b){return (a > b) ? a : b;}
ll min(ll a, ll b){return (a < b) ? a : b;}
ll LASTBIT(ll mask){return (mask) & (-mask);}
long pop_cnt(ll mask){return __builtin_popcountll(mask);}
long ctz(ll mask){return __builtin_ctzll(mask);}
long clz(ll mask){return __builtin_clzll(mask);}
long logOf(ll mask){return 63 - clz(mask);}
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
void debug(){cout.flush();}
template <class T1, class T2>
bool maximize(T1 &a, T2 b){
if (a < b) {a = b; return true;}
return false;
}
template <class T1, class T2>
bool minimize(T1 &a, T2 b){
if (a > b) {a = b; return true;}
return false;
}
template <class T>
void printArr(T& container, char separator = ' ', char finish = '\n'){
for(auto item: container) cout << item << separator;
cout << finish;
}
template <class T>
void remove_dup(vector<T> &a){
sort(ALL(a));
a.resize(unique(ALL(a)) - a.begin());
}
struct PST{
struct Node{
int child[2], cnt;
ll sum;
Node(){memset(child, -1, sizeof child); sum = cnt = 0;}
};
int L, R;
vector<Node> a;
vector<int> version;
PST(int _L, int _R, int _n = 1){
L = _L, R = _R;
a.reserve(_n);
}
void add_child(int &x){
x = a.size();
a.push_back(Node());
}
void new_tree(){
version.push_back(a.size());
a.push_back(Node());
build_tree(L, R, version.back());
}
void build_tree(int l, int r, int id){
if (l == r) return;
int mid = (l + r) >> 1;
add_child(a[id].child[0]); add_child(a[id].child[1]);
build_tree(l, mid, a[id].child[0]);
build_tree(mid + 1, r, a[id].child[1]);
}
void update(int i, pair<int, ll> val, int l, int r, int prev_id, int id){
a[id].cnt = a[prev_id].cnt + val.first;
a[id].sum = a[prev_id].sum + val.second;
if (l == r) {
return;
}
int mid = (l + r) >> 1;
a[id].child[0] = a[prev_id].child[0];
a[id].child[1] = a[prev_id].child[1];
if (i <= mid){
add_child(a[id].child[0]);
update(i, val, l, mid, a[prev_id].child[0], a[id].child[0]);
}
else{
add_child(a[id].child[1]);
update(i, val, mid + 1, r, a[prev_id].child[1], a[id].child[1]);
}
}
void update(int i, pair<int, ll> val, int id = -1){
if (id == -1) id = version.back();
version.push_back(0);
add_child(version.back());
update(i, val, L, R, id, version.back());
}
array<ll, 3> walk(ll c, int id1, int id2, int id3){
array<ll, 3> ans = {0, 0, 0};
int l = L, r = R;
ll cnt = 0, sum = 0;
while(l < r){
int mid= (l + r) >> 1;
if (a[a[id1].child[0]].sum + a[a[id2].child[0]].sum - 2*a[a[id3].child[0]].sum < c){
c -= a[a[id1].child[0]].sum + a[a[id2].child[0]].sum- 2*a[a[id3].child[0]].sum;
cnt += a[a[id1].child[0]].cnt + a[a[id2].child[0]].cnt- 2*a[a[id3].child[0]].cnt;
sum += a[a[id1].child[0]].sum + a[a[id2].child[0]].sum- 2*a[a[id3].child[0]].sum;
id1 = a[id1].child[1];
id2 = a[id2].child[1];
id3 = a[id3].child[1];
l = mid + 1;
}
else{
id1 = a[id1].child[0];
id2 = a[id2].child[0];
id3 = a[id3].child[0];
r = mid;
}
}
cnt += a[id1].cnt + a[id2].cnt- 2*a[id3].cnt;
sum += a[id1].sum + a[id2].sum- 2*a[id3].sum;
ans[0] = l;
ans[1] = cnt;
ans[2] = sum;
return ans;
}
};
const int N = 1e5 + 69, LOG_N = 17;
const int INF = 1e9 + 69;
int n, m, q;
vector<pair<int, int>> graph[N];
vector<ll> lmao[N];
vector<int> b;
int state[N], g[N];
int h[N], parent[N][LOG_N];
void dfs(int u, int p, int cur, PST &st){
h[u] = h[p] + 1;
for(int j = 1; MASK(j) < h[u]; ++j)
parent[u][j] = parent[parent[u][j-1]][j-1];
state[u] = cur;
for(pair<int, int> v: graph[u]) if (v.first != p){
parent[v.first][0] = u;
g[v.first] = g[u] + lmao[v.second].size();
if (lmao[v.second].empty()){
dfs(v.first, u, cur, st);
}
else{
int _cur = cur;
for(ll j: lmao[v.second]){
int idx = lower_bound(ALL(b), j) - b.begin();
st.update(idx, {1, j}, _cur);
_cur = st.version.back();
}
dfs(v.first, u, _cur, st);
}
}
}
int LCA(int u, int v){
if (h[u] < h[v]) swap(u, v);
int diff = h[u] - h[v];
for(int j = 0; j < LOG_N; ++j) if (GETBIT(diff, j))
u = parent[u][j];
if (u == v) return u;
for(int j = LOG_N - 1; j>=0; --j) if (parent[u][j] != parent[v][j]){
u = parent[u][j];
v = parent[v][j];
}
return parent[u][0];
}
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n >> m >> q;
for(int i= 1; i<n; ++i){
int u, v; cin >> u >> v;
graph[u].push_back({v, i});
graph[v].push_back({u, i});
}
for(int i = 0; i<m; ++i){
int p, k; cin >> p >> k;
lmao[p].push_back(k);
b.push_back(k);
}
b.push_back(INF);
remove_dup(b);
m = b.size();
PST st(0, m-1, n * 20);
st.new_tree();
dfs(1, 0, 0, st);
while(q--){
ll u, v, x, y; cin >> u >> v >> x >> y;
int lck = LCA(u, v);
array<ll, 3> ans = st.walk(y, state[u], state[v], state[lck]);
int gold_cnt = g[u] + g[v] - 2 * g[lck];
if (ans[2] <= y){
gold_cnt -= ans[1];
}
else{
ll diff = ans[2] - y;
if (diff % b[ans[0]] == 0) diff /= b[ans[0]];
else diff = diff / b[ans[0]] + 1;
gold_cnt -= ans[1] - diff;
}
if (gold_cnt <= x) cout << x - gold_cnt << "\n";
else cout << -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... |