Submission #846648

#TimeUsernameProblemLanguageResultExecution timeMemory
846648biximoTwo Currencies (JOI23_currencies)C++17
100 / 100
1119 ms48728 KiB
#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 timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...