Submission #1262018

#TimeUsernameProblemLanguageResultExecution timeMemory
1262018M_W_13Two Currencies (JOI23_currencies)C++20
100 / 100
3891 ms41812 KiB
#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
#define rep(i, n) for (int i = 0; i < (n); i++)
#define st first
#define nd second
#define pb push_back
const int MAXN = 1 << 17;
const int MAXK = 20;
int n, m, q;
int skok[MAXN][MAXK];
int depth[MAXN];
int pot[MAXK];
ll pom[MAXN];
bool czy[MAXN];
vector<pair<int, ll>> jakie[MAXN];
ll liczba[MAXN];
ll ile[MAXN];
int policz[MAXN];
int ans[MAXN];
int lastans[MAXN];
int preorder[MAXN];
int postorder[MAXN];
vector<int> graf[MAXN];
pair<ll, ll> monety[MAXN];
vector<pair<pair<int, int>, ll>> vec;
int kt = 1;
int kt2 = 1;
int uz = 0;

struct trojka {
    int a, b, c;
};

trojka pyt[MAXN];

void dfs(int v, int last) {
    preorder[v] = kt;
    kt++;
    depth[v] = depth[last] + 1;
    skok[v][0] = last;
    for (int k = 1; k < MAXK; k++) {
        skok[v][k] = skok[skok[v][k - 1]][k - 1];
    }
    for (auto w: graf[v]) {
        if (w == last) continue;
        dfs(w, v);
    }
    postorder[v] = kt2;
    kt2++;
}

int lca(int a, int b) {
    if (depth[a] > depth[b]) {
        swap(a, b);
    }
    int k = MAXK - 1;
    while (depth[a] != depth[b]) {
        if ((depth[b] - pot[k]) >= depth[a]) {
            b = skok[b][k];
        }
        k--;
    }
    if (a == b) {
        return a;
    }
    k = MAXK - 1;
    while (skok[a][0] != skok[b][0]) {
        if (skok[a][k] != skok[b][k]) {
            a = skok[a][k];
            b = skok[b][k];
        }
        k--;
    }
    return skok[a][0];
}

void dfs2(int v, int last, ll val, int val2) {
    val += pom[v];
    val2 += policz[v];
    // cout << "v = " << v << '\n';
    for (auto p: jakie[v]) {
        // cout << "nr = " << p.st << " ile = " << p.nd << '\n';
        ile[p.st] += (val * p.nd);
        ans[p.st] += (val2 * p.nd);
    }
    for (auto syn: graf[v]) {
        if (syn == last) continue;
        dfs2(syn, v, val, val2);
    }
}

bool czyojc(int a, int b) {
    if (preorder[a] <= preorder[b] && postorder[a] >= postorder[b]) {
        return true;
    }
    return false;
}

void zrob() {
    dfs2(1, 1, 0ll, 0);
    rep(i, q) {
        if (czy[i]) continue;
        // cout << "liczba = " << liczba[i] << " ile = " << ile[i] << '\n';
        if (ile[i] >= liczba[i]) {
            // cout << "i = " << i << endl;
            czy[i] = true;
            int it = 0;
            int t = 0;
            while (liczba[i] > 0) {
                int x = vec[it].st.st;
                int y = vec[it].st.nd;
                ll lic = vec[it].nd;
                // cout << "x = " << x << " y = " << y << " lic = " << lic << '\n';
                if (czyojc(pyt[i].c, x) && (czyojc(y, pyt[i].a) || czyojc(y, pyt[i].b))) {
                    // cout << "TAK" << endl;
                    t++;
                    liczba[i] -= lic;
                }
                it++;
            }
            if (liczba[i] < 0) {
                t--;
            }
            // cout << "i = " << i << " t = " << t << '\n';
            ans[i] -= (lastans[i] + t);
        }
        else {
            liczba[i] -= ile[i];
        }
    }
    rep(i, q) {
        lastans[i] = ans[i];
        ile[i] = 0;
    }
    rep(i, n + 1) {
        pom[i] = 0;
        policz[i] = 0;
    }
    vec.clear();
}

int main() {
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    pot[0] = 1;
    for (int k = 1; k < MAXK; k++) {
        pot[k] = pot[k - 1] * 2;
    }

    cin >> n >> m >> q;
    vector<pair<int, int>> kraw;
    int sqr = 330;
    rep(i, n - 1) {
        int a, b;
        cin >> a >> b;
        graf[a].pb(b);
        graf[b].pb(a);
        kraw.pb({a, b});
    }
    dfs(1, 1);
    vector<pair<ll, int>> checks;
    rep(i, m) {
        int p;
        ll c;
        cin >> p >> c;
        p--;
        checks.pb({c, p});
    }
    rep(i, q) {
        int a, b;
        ll x, y;
        cin >> a >> b >> x >> y;
        monety[i] = {x, y};
        liczba[i] = y;
        int c = lca(a, b);
        pyt[i] = {a, b, c};
        jakie[a].pb({i, 1});
        jakie[b].pb({i, 1});
        jakie[c].pb({i, -2});
    }
    sort(checks.begin(), checks.end());
    for (auto p: checks) {
        int x = kraw[p.nd].st;
        int y = kraw[p.nd].nd;
        if (czyojc(y, x)) {
            swap(x, y);
        }
        vec.pb({{x, y}, p.st});
        policz[y]++;
        pom[y] += p.st;
        int sz = vec.size();
        if (sz >= sqr) {
            zrob();
        }
    }
    zrob();
    rep(i, q) {
        if (!czy[i]) {
            ans[i] = 0;
        }
        ll odp = monety[i].st - (long long)ans[i];
        if (odp < 0) {
            cout << -1 << '\n';
        }
        else {
            cout << odp << '\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...