제출 #1248714

#제출 시각아이디문제언어결과실행 시간메모리
1248714enxiayyTwo Currencies (JOI23_currencies)C++20
100 / 100
2106 ms53556 KiB
#include <bits/stdc++.h>
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define compact(v) v.erase(unique(all(v)), v.end())
#define dbg(v) "[" #v " = " << (v) << "]"
#define el "\n"

using namespace std;
typedef long long ll;
typedef long double ld;

mt19937_64 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
long long randRange(long long l, long long r){ return uniform_int_distribution<long long>(l,r)(rng); }

const int N = 2e5 + 5;
const int LOG = 20;

int n, m, q;
vector <int> adj[N];
int p[N], c[N];
pair<int, int> tmp[N];
int L[N], R[N], ANS[N];

struct edge {
    int u, v;
    ll cost;
    edge(int u = 0, int v = 0, ll cost = 0) : u(u), v(v), cost(cost) {}

    bool operator < (const edge& o) const {
        return cost < o.cost;
    }
};

edge edges[N];
int lft[N][LOG + 5], chain_id[N], head_chain[N], high[N], tin[N], tout[N], sz[N], timer = 0, cur_chain = 0;

struct BIT {
    vector <ll> bit;
    int n;

    BIT(int n = 0) : n(n), bit(n + 5, 0) {}

    void update(int pos, ll val) {
        while(pos <= n) {
            bit[pos] += val;
            pos += pos & -pos;
        }
    }

    void upd(int l, int r, ll val) {
        if (l > r) return;
        update(r, val);
    }

    ll get(int pos) {
        ll res = 0;
        while(pos) {
            res += bit[pos];
            pos -= pos & -pos;
        }
        return res;
    }

    ll query(int l, int r) {
        return get(r) - get(l - 1);
    }

    void reset() {
        for(int i = 0; i <= n; ++i)
            bit[i] = 0;
    }
};

void dfs_lca(int u) {
    sz[u] = 1;
    for(int v : adj[u]) {
        if (v == lft[u][0]) continue;
        high[v] = high[u] + 1;
        lft[v][0] = u;
        dfs_lca(v);
        sz[u] += sz[v];
    }
}

namespace LCA {
    void prepare_lca() {
        dfs_lca(1);
        high[0] = -1;
        
        for(int j = 1; j <= LOG; ++j) {
            for(int i = 1; i <= n; ++i) {
                lft[i][j] = lft[lft[i][j - 1]][j - 1];
            }
        }
    }

    int get_lca(int u, int v) {
        if (high[u] < high[v])
            swap(u, v);

        int k = high[u] - high[v];
        for(int i = 0; (1 << i) <= k; ++i) {
            if (k >> i & 1) {
                u = lft[u][i];
            }
        }

        if (u == v) return u;

        for(int i = LOG; i >= 0; --i) {
            if (lft[u][i] != lft[v][i]) {
                u = lft[u][i];
                v = lft[v][i];
            }
        }

        return lft[u][0];
    }
} using namespace LCA;

void build_hld(int u, int par) {
    if (head_chain[cur_chain] == 0) {
        head_chain[cur_chain] = u;
    }
    chain_id[u] = cur_chain;
    tin[u] = ++timer;
    
    int fat = -1;
    for(int v : adj[u]) {
        if (v == par) continue;
        if (fat == -1 || sz[fat] < sz[v]) {
            fat = v;
        }
    }

    if (fat != -1)
        build_hld(fat, u);

    for(int v : adj[u]) {
        if (v == par || v == fat) continue;
        ++cur_chain;
        build_hld(v, u);
    }
    tout[u] = timer;
}

void prepare_hld() {
    prepare_lca();
    build_hld(1, -1);
}

struct HLD {
    BIT ft;
    int n;

    HLD(int n = 0) : n(n), ft(BIT(n)) {}

    ll query_hld(int u, int v) {
        int lca = get_lca(u, v);
        ll res = 0;

        while(chain_id[u] != chain_id[lca]) {
            res += ft.query(tin[head_chain[chain_id[u]]], tin[u]);
            u = lft[head_chain[chain_id[u]]][0];
        }

        while(chain_id[v] != chain_id[lca])  {
            res += ft.query(tin[head_chain[chain_id[v]]], tin[v]);
            v = lft[head_chain[chain_id[v]]][0];
        }

        if (high[u] < high[v]) res += ft.query(tin[u] + 1, tin[v]);
        else res += ft.query(tin[v] + 1, tin[u]);

        return res;
    }

    void update_hld(int u, int v, ll val) {
        int lca = get_lca(u, v);
        // cerr << u << " " << " " << v << el;
        // cerr << lca << el;
        // cerr << "_____________________" << el;
        while(chain_id[u] != chain_id[lca]) {
            ft.upd(tin[head_chain[chain_id[u]]], tin[u], val);
            // cerr << "%%%" << el;
            // cerr << head_chain[chain_id[u]] << " " << u << el;
            // cerr << tin[head_chain[chain_id[u]]] << " " << tin[u] << el;
            // cerr << "%%%" << el;
            u = lft[head_chain[chain_id[u]]][0];

        }

        while(chain_id[v] != chain_id[lca]) {
            ft.upd(tin[head_chain[chain_id[v]]], tin[v], val);
            // cerr << "%%%" << el;
            // cerr << head_chain[chain_id[v]] << " " << v << el;
            // cerr << tin[head_chain[chain_id[v]]] << " " << tin[v] << el;
            // cerr << "%%%" << el;
            v = lft[head_chain[chain_id[v]]][0];
        }

        // cerr << "LAST: " << el;
        // cerr << high[u] << " " << high[v] << el;
        // cerr << query_hld(1, 10) << el;
        if (high[u] < high[v]) ft.upd(tin[u] + 1, tin[v], val);
        else ft.upd(tin[v] + 1, tin[u], val);
    }

    void reset() {
        ft.reset();
    }
};

struct query {
    int s, t, x, id;
    ll y;

    query(int s = 0, int t = 0, int x = 0, ll y = 0, int id = 0) : s(s), t(t), x(x), y(y), id(id) {}  
} eq[N];

vector <int> queries[N];

void solve() {
    cin >> n >> m >> q;
    for(int i = 1; i < n; ++i) {
        int u, v; cin >> u >> v;
        adj[u].eb(v);
        adj[v].eb(u);        
        tmp[i] = {u, v};
    }

    for(int i = 1; i <= m; ++i) {
        cin >> p[i] >> c[i];
        edges[i] = edge(tmp[p[i]].first, tmp[p[i]].second, c[i]);
    }

    sort(edges + 1, edges + 1 + m);

    for(int i = 1; i <= q; ++i) {
        cin >> eq[i].s >> eq[i].t >> eq[i].x >> eq[i].y;
        eq[i].id = i;
    }

    for(int i = 1; i <= q; ++i) {
        L[i] = 0;
        R[i] = m;
        ANS[i] = -1;
    }

    prepare_hld();
    HLD hld1(n), hld2(n);
    
    
    // for(int i = 1; i <= m; ++i) {
    //     cerr << edges[i].u << " " << edges[i].v << " " << edges[i].cost << el;
    // }
    // cerr << el;

    // hld1.update_hld(edges[1].u, edges[1].v, edges[1].cost);


    while(true) {
        bool finished = true;
        for(int i = 1; i <= q; ++i) {
            if (L[i] <= R[i]) {
                queries[(L[i] + R[i]) >> 1].push_back(i);
                finished = false;
            }
        }

        if (finished == true) break;

        for(int i = 1; i <= m; ++i) {
            hld2.update_hld(edges[i].u, edges[i].v, 1);
        }

        for(int mid = 0; mid <= m; ++mid) {
            if (mid > 0) {
                hld1.update_hld(edges[mid].u, edges[mid].v, edges[mid].cost);
                hld2.update_hld(edges[mid].u, edges[mid].v, -1);
            }
        
            for(auto _ : queries[mid]) {
                int s = eq[_].s;
                int t = eq[_].t;
                int x = eq[_].x;
                ll y = eq[_].y;
                int id = eq[_].id;

                ll silver = hld1.query_hld(s, t);
                int gold = hld2.query_hld(s, t);

                if (silver <= y) {
                    ANS[id] = max(ANS[id], x - gold);
                    L[_] = mid + 1;
                }
                else {
                    R[_] = mid - 1;
                }
            }
            queries[mid].clear();
        }

        hld1.reset();
        hld2.reset();
    }

    for(int i = 1; i <= q; ++i) {
        cout << ANS[i] << el;
    }

}

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

    #define task "task" 
    if(fopen(task".inp", "r")) {
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    solve();

    return 0;
}

/*

*/

컴파일 시 표준 에러 (stderr) 메시지

currencies.cpp: In function 'int main()':
currencies.cpp:320:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  320 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
currencies.cpp:321:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  321 |         freopen(task".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...