This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
//
// Created by 42kangaroo on 26/01/2024.
//
#include "bits/stdc++.h"
using namespace std;
#define int long long
using g_t = vector<vector<int>>;
struct SegAb {
int st, en, se;
};
struct Node {
int l, r, bl, br, numL, sumL;
};
struct PSegTe {
vector<Node> a;
vector<int> cooC;
int high;
int build(int l, int r) {
int act = a.size();
a.push_back({-1, -1, l, r, 0, 0});
if (l + 1 < r) {
int m = (l + r) / 2;
a[act].l = build(l, m);
a[act].r = build(m, r);
}
return act;
}
pair<int, int> get(int st, int k) {
if (a[st].br <= k) return {a[st].numL, a[st].sumL};
if (a[st].bl >= k) return {0, 0};
pair<int, int> res = {0, 0};
if (a[st].l != -1) {
auto re = get(a[st].l, k);
res.first += re.first;
res.second += re.second;
re = get(a[st].r, k);
res.first += re.first;
res.second += re.second;
}
return res;
}
int add(int st, int k, int v) {
if (a[st].bl > k || a[st].br <= k) return st;
int nN = a.size();
a.push_back({-1, -1, a[st].bl, a[st].br, 0, 0});
if (a[st].l != -1) {
a[nN].l = add(a[st].l, k, v);
a[nN].r = add(a[st].r, k, v);
a[nN].numL = a[a[nN].l].numL + a[a[nN].r].numL;
a[nN].sumL = a[a[nN].l].sumL + a[a[nN].r].sumL;
} else {
a[nN].numL = a[st].numL + 1;
a[nN].sumL = a[st].sumL + v;
}
return nN;
}
};
int dfs(int n, int p, int d, g_t &g, vector<int> &pa, vector<int> &de) {
de[n] = d;
int su = 1;
int ma = 0;
pa[n] = p;
for (auto &e: g[n]) {
if (e == p) continue;
int re = dfs(e, n, d + 1, g, pa, de);
su += re;
if (re > ma) {
swap(e, g[n][0]);
ma = re;
}
}
return su;
}
void segDfs(int n, int p, int seg, g_t &g, vector<PSegTe> &segs, vector<int> &segThis, g_t &cos) {
segThis[n] = seg;
if (seg == -1) {
segThis[n] = segs.size();
segs.push_back({{}, {}, n});
}
for (auto e: cos[n]) {
segs[segThis[n]].cooC.push_back(e);
}
bool first = true;
for (auto e: g[n]) {
if (e == p) continue;
if (first) {
segDfs(e, n, segThis[n], g, segs, segThis, cos);
first = false;
} else {
segDfs(e, n, -1, g, segs, segThis, cos);
}
}
}
void initSegDfs(int n, int p, int st, g_t &g, vector<PSegTe> &segs,
vector<int> &segThis, vector<int> &topSeg, g_t &cos) {
topSeg[n] = st;
for (auto e: cos[n]) {
topSeg[n] = segs[segThis[n]].add(topSeg[n], std::lower_bound(segs[segThis[n]].cooC.begin(),
segs[segThis[n]].cooC.end(), e) -
segs[segThis[n]].cooC.begin(), e);
}
bool first = true;
for (auto e: g[n]) {
if (e == p) continue;
if (first) {
initSegDfs(e, n, topSeg[n], g, segs, segThis, topSeg, cos);
first = false;
} else {
initSegDfs(e, n, 0, g, segs, segThis, topSeg, cos);
}
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, q;
cin >> n >> m >> q;
vector<pair<int, int>> edge(n - 1);
g_t g(n);
for (int i = 0; i < n - 1; ++i) {
int a, b;
cin >> a >> b;
--a; --b;
g[a].push_back(b);
g[b].push_back(a);
edge[i] = {a, b};
}
vector<int> p(n);
vector<int> d(n);
dfs(0, 0, 0, g, p, d);
for (int i = 0; i < n - 1; ++i) {
if (p[edge[i].first] != edge[i].second) swap(edge[i].first, edge[i].second);
}
g_t cos(n);
for (int i = 0; i < m; ++i) {
int pj, c;
cin >> pj >> c;
pj--;
cos[edge[pj].first].push_back(c);
}
vector<PSegTe> segs;
vector<int> segThis(n);
segDfs(0, 0, -1, g, segs, segThis, cos);
for (auto &seg: segs) {
std::sort(seg.cooC.begin(), seg.cooC.end());
seg.cooC.erase(std::unique(seg.cooC.begin(), seg.cooC.end()), seg.cooC.end());
seg.build(0, seg.cooC.size());
}
vector<int> topSeg(n);
initSegDfs(0, 0, 0, g, segs, segThis, topSeg, cos);
for (int i = 0; i < q; ++i) {
int a, b, gol, sil;
cin >> a >> b >> gol >> sil;
--a;
--b;
vector<SegAb> abs;
while (segThis[a] != segThis[b]) {
if (d[segs[segThis[a]].high] < d[segs[segThis[b]].high]) swap(a, b);
abs.push_back({a, -1, segThis[a]});
a = p[segs[segThis[a]].high];
}
if (d[a] < d[b]) swap(a, b);
if (a != b) {
abs.push_back({a, b, segThis[a]});
}
int numChe = 0;
for (auto &e: abs) {
numChe += segs[e.se].a[topSeg[e.st]].numL;
if (e.en != -1) {
numChe -= segs[e.se].a[topSeg[e.en]].numL;
}
}
int l = 0, r = 1e9 + 1;
while (l + 1 < r) {
m = (l + r) / 2;
int su = 0;
for (auto &e: abs) {
int k = std::upper_bound(segs[e.se].cooC.begin(), segs[e.se].cooC.end(), m) - segs[e.se].cooC.begin();
su += segs[e.se].get(topSeg[e.st], k).second;
if (e.en != -1) {
su -= segs[e.se].get(topSeg[e.en], k).second;
}
}
if (su >= sil) r = m;
else l = m;
}
int su = 0;
int nuS = 0;
for (auto &e: abs) {
int k = std::upper_bound(segs[e.se].cooC.begin(), segs[e.se].cooC.end(), r) - segs[e.se].cooC.begin();
auto res = segs[e.se].get(topSeg[e.st], k);
su += res.second;
nuS += res.first;
if (e.en != -1) {
res = segs[e.se].get(topSeg[e.en], k);
su -= res.second;
nuS -= res.first;
}
}
int dif = su - sil;
nuS -= (dif + r - 1)/r;
numChe -= nuS;
if (gol - numChe < -1) numChe = gol + 1;
cout << gol - numChe << "\n";
}
}
# | 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... |