제출 #1355555

#제출 시각아이디문제언어결과실행 시간메모리
1355555otariusTwo Currencies (JOI23_currencies)C++20
100 / 100
941 ms56368 KiB
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace __gnu_pbds;
using namespace std;

// #pragma GCC optimize("Ofast")
// #pragma GCC optimize ("unroll-loops")
// #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#define ff first
#define sc second
#define pb push_back
#define ll long long
#define pll pair<ll, ll>
#define pii pair<int, int>
#define ull unsigned long long
#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
mt19937_64 rngl(chrono::steady_clock::now().time_since_epoch().count());

#define int long long
// #define int unsigned long long

// #define ordered_set(T) tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>
// #define ordered_multiset(T) tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>

// const ll mod = 1e9 + 7;
// const ll mod = 998244353;

const ll inf = 1e9;
const ll biginf = 1e18;
const int maxN = 1e5 + 15;

vector<int> g[maxN], qs[maxN];
int n, m, q, a[maxN], b[maxN], p[maxN], c[maxN], s[maxN], t[maxN], x[maxN], y[maxN], in[maxN], out[maxN], par[maxN][20], tim;
struct BIT {
    int fen[maxN];
    void init() {
        for (int i = 0; i <= n; i++) fen[i] = 0;
    }
    
    void update(int x, int d) {
        for ( ; x <= n; x += (x & -x)) fen[x] += d;
    }

    int get(int x) {
        int ans = 0;
        for ( ; x; x -= (x & -x)) ans += fen[x];
        return ans;
    }
} f1, f2;

void dfs(int v, int p) {
    in[v] = ++tim;
    par[v][0] = p;
    for (int u : g[v]) {
        if (u == p) continue;
        dfs(u, v);
    }

    out[v] = tim;
}
bool is_anc(int x, int y) {
    return (in[x] <= in[y] && out[x] >= out[y]);
}
int lca(int x, int y) {
    if (is_anc(x, y)) return x;
    if (is_anc(y, x)) return y;
    for (int j = 19; j >= 0; j--)
        if (!is_anc(par[x][j], y)) x = par[x][j];
    return par[x][0];
}
void solve() {
    cin >> n >> m >> q;
    for (int i = 1; i < n; i++)
        cin >> a[i] >> b[i];
    for (int i = 1; i <= m; i++)
        cin >> p[i] >> c[i];
    for (int i = 1; i <= q; i++)
        cin >> s[i] >> t[i] >> x[i] >> y[i];

    for (int i = 1; i < n; i++)
        g[a[i]].pb(b[i]), g[b[i]].pb(a[i]);
    dfs(1, 1);

    for (int j = 1; j < 20; j++) {
        for (int i = 1; i <= n; i++) {
            par[i][j] = par[par[i][j - 1]][j - 1];
        }
    }

    for (int i = 1; i < n; i++)
        if (is_anc(b[i], a[i])) swap(a[i], b[i]);

    auto comp = [&](int a, int b) {
        return c[a] < c[b];
    };

    int ord[m + 1];
    iota(ord + 1, ord + m + 1, 1);
    sort(ord + 1, ord + m + 1, comp);

    int l[q + 1], r[q + 1], ans[q + 1];
    for (int i = 1; i <= q; i++)
        l[i] = 0, r[i] = m;

    while (1) {
        f1.init(); f2.init();
        for (int i = 0; i <= m; i++) qs[i].clear();

        bool f = 0;
        for (int i = 1; i <= q; i++) {
            if (l[i] <= r[i]) {
                f = 1; qs[(l[i] + r[i]) / 2].pb(i);
            }
        }

        if (!f) break;

        for (int i = 1; i <= m; i++) {
            f1.update(in[b[p[ord[i]]]], 1);
            f1.update(out[b[p[ord[i]]]] + 1, -1);
        }

        for (int i = 0; i <= m; i++) {
            if (i) {
                f1.update(in[b[p[ord[i]]]], -1);
                f1.update(out[b[p[ord[i]]]] + 1, 1);
                f2.update(in[b[p[ord[i]]]], c[ord[i]]);
                f2.update(out[b[p[ord[i]]]] + 1, -c[ord[i]]);
            }

            for (int j : qs[i]) {
                int sum = f2.get(in[s[j]]) + f2.get(in[t[j]]) - 2 * f2.get(in[lca(s[j], t[j])]);
                if (sum <= y[j]) {
                    ans[j] = f1.get(in[s[j]]) + f1.get(in[t[j]]) - 2 * f1.get(in[lca(s[j], t[j])]); l[j] = i + 1;
                } else r[j] = i - 1;
            }
        }
    }

    for (int i = 1; i <= q; i++)
        cout << max(x[i] - ans[i], -1LL) << '\n';
}
int32_t main() { 
// #ifndef ONLINE_JUDGE
//     freopen("input.txt", "r", stdin);
//     freopen("output.txt", "w", stdout);
// #endif
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    
    int t = 1;
    // cin >> t;
    while (t--) {
        solve();
        cout << '\n';
    }
    return 0;
}
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…