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;
using p = pair<int, int>;
const int MAX_N = 100105;
int n, m, q, id=1, len=131072, ids[MAX_N], sz[MAX_N], depth[MAX_N] = {0};
long long tree[262144];
vector<int> paths[MAX_N];
vector<p> pathsA;
int table[18][MAX_N];
int LCA(int a, int b) {
if(depth[a] != depth[b]) {
if(depth[a] < depth[b]) swap(a, b);
int diff = depth[a] - depth[b];
for(int i = 17; i >= 0; i --) {
if(diff & (1 << i)) {
a = table[i][a];
}
}
}
assert(depth[a] == depth[b]);
for(int i = 17; i >= 0; i --) {
if(table[i][a] != table[i][b]) {
a = table[i][a];
b = table[i][b];
}
}
if(a != b) a = table[0][a];
return a;
}
void calcTable() {
for(int i = 1; i < 18; i ++) {
for(int j = 1; j <= n; j ++) {
table[i][j] = table[i - 1][table[i - 1][j]];
}
}
}
void dfs(int cur=1, int prev=-1) {
ids[cur] = id ++;
sz[cur] = 1;
for(int i: paths[cur]) {
if(i == prev) continue;
table[0][i] = cur;
depth[i] = depth[cur] + 1;
dfs(i, cur);
sz[cur] += sz[i];
}
}
void update(int a, int v) {
a += len;
tree[a] += (long long)v;
for(a /= 2; a >= 1; a /= 2) {
tree[a] = tree[a * 2] + tree[a * 2 + 1];
}
}
void rangeUpdate(int a, int v) {
int b = ids[a] + sz[a];
// if(ids[a] <= 10) assert(b >= 1863);
a = ids[a];
update(a, v);
update(b, -v);
}
long long query(int a, int b) {
a += len;
b += len;
long long tot = 0;
for(; a <= b; a /= 2, b /= 2) {
if(a & 1) {
tot += tree[a ++];
}
if(!(b & 1)) {
tot += tree[b --];
}
}
return tot;
}
long long query(int b) {
int a = 0;
b = ids[b];
return query(a, b);
}
vector<p> sts, lh;
vector<int> ans, cnts, mids[MAX_N];
struct N {
int a, b, c;
long long g, s;
N() {}
};
vector<N> qs;
int main() {
// cin.tie(0)->sync_with_stdio(0);
cin >> n >> m >> q;
for(int i = 1; i < n; i ++) {
int a, b;
cin >> a >> b;
paths[a].push_back(b);
paths[b].push_back(a);
pathsA.push_back({a, b});
}
dfs(); calcTable();
sts.resize(m);
for(int i = 0; i < m; i ++) {
cin >> sts[i].second >> sts[i].first;
sts[i].second --;
sts[i].second = depth[pathsA[sts[i].second].first] > depth[pathsA[sts[i].second].second] ? pathsA[sts[i].second].first : pathsA[sts[i].second].second;
}
sort(sts.begin(), sts.end());
qs.resize(q); ans.resize(q); lh.resize(q); cnts.resize(q);
for(int i = 0; i < q; i ++) {
cin >> qs[i].a >> qs[i].b >> qs[i].g >> qs[i].s;
qs[i].c = LCA(qs[i].a, qs[i].b);
lh[i] = {0, m - 1};
ans[i] = -1;
}
while(1) {
bool emp = true;
for(int i = 0; i < q; i ++) {
auto&[low, high] = lh[i];
if(low > high) continue;
emp = false;
mids[(low + high) >> 1].push_back(i);
}
for(auto&i: tree) i = 0;
for(int l = 0; l < m; l ++) {
auto&[C, P] = sts[l];
rangeUpdate(P, (emp ? 1 : C));
for(auto i: mids[l]) {
N& q = qs[i];
long long cs = query(q.a) + query(q.b) - query(q.c) * 2LL;
if(cs < 0) {
cout << query(q.a) << " " << query(q.b) << " " << query(q.c) << "\n";
cout << depth[q.a] << " " << depth[q.b] << " " << depth[q.c] << "\n";
cout << ids[q.a] << " " << ids[q.b] << " " << ids[q.c] << "\n";
cout << cs << "\n";
assert(0 != 0);
}
assert(cs >= 0);
auto&[low, high] = lh[i];
if(cs <= q.s) {
ans[i] = l;
low = l + 1;
} else {
high = l - 1;
}
}
mids[l].clear();
}
if(emp) {
for(int i = 0; i < q; i ++) {
N& q = qs[i];
cnts[i] = (int)(query(q.a) + query(q.b) - query(q.c) * 2);
if(ans[i] >= 0) mids[ans[i]].push_back(i);
}
for(auto&i: tree) i = 0;
break;
}
}
for(int l = 0; l < m; l ++) {
auto&[C, P] = sts[l];
rangeUpdate(P, 1);
for(auto i: mids[l]) {
N& q = qs[i];
int cs = (int)(query(q.a) + query(q.b) - query(q.c) * 2);
cnts[i] -= cs;
}
}
for(int i = 0; i < q; i ++) {
if(cnts[i] <= qs[i].g) cout << qs[i].g - cnts[i] << "\n";
else cout << "-1\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... |