Submission #1336825

#TimeUsernameProblemLanguageResultExecution timeMemory
1336825aaaaaaaaTwo Currencies (JOI23_currencies)C++20
0 / 100
23 ms2152 KiB
#include <bits/stdc++.h>
using namespace std;

const int mxN = 2e5 + 1000;
const int mxB = 20;

#define all(x) x.begin(), x.end()

vector<int> point[mxN];
vector<pair<int, int>> adj[mxN];
vector<pair<int, int>> edges, checkpoints;
vector<tuple<int, int, int, int, int, int>> Query;
vector<int> euler;
int tin[mxN], tout[mxN], st[mxN], en[mxN], stt[mxN], enn[mxN], depth[mxN], leader[mxN], ans[mxN], ok[mxN], tim = -1;
pair<int, int> dp[mxN * 4][mxB];
pair<long long, int> seg[mxN * 4];

pair<long long, int> combine(const pair<long long, int> &left, const pair<long long, int> &right){
    return {left.first + right.first, left.second + right.second};
}

void update(int node, int start, int end, int idx, pair<long long, int> val){
    if(start == end){
        seg[node].first += val.first, seg[node].second += val.second;
        return;
    }
    int mid = start + (end - start) / 2;
    if(idx <= mid) update(node * 2 + 1, start, mid, idx, val);
    else update(node * 2 + 2, mid + 1, end, idx, val);
    seg[node] = combine(seg[node * 2 + 1], seg[node * 2 + 2]);
}

void update(int idx, pair<long long, int> val){
    update(0, 0, tim, idx, val);
}

pair<long long, int> query(int node, int start, int end, int l, int r){
    if(start > r || end < l) return {0, 0};
    if(start >= l && end <= r) return seg[node];
    int mid = start + (end - start) / 2;
    return combine(query(node * 2 + 1, start, mid, l, r), query(node * 2 + 2, mid + 1, end, l, r));
}

void dfs(int u = 1, int par = 0){
    tin[u] = ++tim, st[u] = (int) euler.size(), depth[u] = depth[par] + 1;
    euler.push_back(u);
    for(auto [v, id] : adj[u]){
        if(v ^ par){
            leader[id] = v;
            dfs(v, u);
            euler.push_back(u);
        }
    }
    en[u] = (int) euler.size();
    euler.push_back(u);
    tout[u] = ++tim;
}

void build(){
    int n = (int) euler.size();
    for(int i = 0; i < n; ++i){
        dp[i][0] = {depth[euler[i]], euler[i]};
    }
    for(int j = 1; j < mxB; ++j){
        for(int i = 0; i + (1 << j) - 1 < n; ++i){
            dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
        }
    }
}

int lca(int u, int v){
    int l = en[u], r = en[v];
    if(l > r) swap(l, r);
    int k = __lg(r - l + 1);
    return min(dp[l][k], dp[r - (1 << k) + 1][k]).second;
}

pair<long long, int> path_sum(int u, int v){
    if(u == v) return {0ll, 0ll};
    int lc = lca(u, v);
    pair<long long, int> ulc = query(0, 0, tim, 0, tin[u]);
    pair<long long, int> vlc = query(0, 0, tim, 0, tin[v]);
    pair<long long, int> l_lc = query(0, 0, tim, 0, tin[lc]);
    return  {ulc.first + vlc.first - 2 * l_lc.first, ulc.second + vlc.second - 2 * l_lc.second};
}

signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);

    int n, m, q;
    cin >> n >> m >> q;

    for(int i = 1; i <= n - 1; ++i){
        int u, v;
        cin >> u >> v;
        adj[u].push_back({v, i});
        adj[v].push_back({u, i});
    }

    dfs();
    build();

    for(int i = 1; i <= m; ++i){
        int edge_id, silver;
        cin >> edge_id >> silver;
        checkpoints.push_back({silver, edge_id});
        update(tin[leader[edge_id]], {0, 1});
        update(tout[leader[edge_id]], {0, -1});
    }

    sort(all(checkpoints));

    for(int i = 0; i < q; ++i) {
        int u, v, gold;
        long long silver;
        cin >> u >> v >> gold >> silver;
        pair<long long, int> x = path_sum(u, v);
        Query.push_back({silver, gold, u, v, i, x.second});
        stt[i] = 0, enn[i] = m - 1, ans[i] = -1;
        point[(stt[i] + enn[i]) / 2].push_back(i);
        if(x.second <= gold) ans[i] = gold - x.second;
    }

    for(auto [v, i] : checkpoints) {
        update(tin[leader[i]], {0, -1});
        update(tout[leader[i]], {0, 1});
    }

    for(int _ = 0; _ < mxB; ++_){
        for(int i = 0; i < m; ++i){
            auto [___, edge_id] = checkpoints[i];
            update(tin[leader[edge_id]], {___, 1});
            update(tout[leader[edge_id]], {-___, -1});

            for(auto que : point[i]){
                auto [silver, gold, u, v, id, total] = Query[que];
                pair<long long, int> cur = path_sum(u, v);
                if(cur.first <= silver){
                    ans[id] = max(ans[id], gold - total + cur.second);
                    stt[id] = i + 1;
                }else{
                    enn[id] = i - 1;
                }
            }

            point[i].clear();
        }

        for(int i = 0; i < q; ++i){
            if(stt[i] <= enn[i]) point[(stt[i] + enn[i]) / 2].push_back(i);
        }

        for(int i = 0; i < m; ++i){
            auto [___, edge_id] = checkpoints[i];
            update(tin[leader[edge_id]], {-___, -1});
            update(tout[leader[edge_id]], {___, 1});
        }
    }

    for(int i = 0; i < q; ++i) cout << ans[i] << "\n";

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...