Submission #990985

#TimeUsernameProblemLanguageResultExecution timeMemory
990985PacybwoahTwo Currencies (JOI23_currencies)C++17
100 / 100
1258 ms46456 KiB
#include<iostream>
#include<vector>
#include<algorithm>
#include<utility>
using namespace std;
typedef long long ll;
int n, m, q, sz;
vector<vector<int>> pts, graph;
vector<pair<int, int>> edges;
vector<ll> cp;
struct Query{
    int s, t;
    ll x, y;
    int id;
    Query(int _s, int _t, ll _x, ll _y, int _id){
        s = _s, t = _t, x = _x, y = _y, id = _id;
    }
};
vector<Query> queries;
vector<ll> ans;
vector<vector<int>> anc;
vector<int> in, out, dep;
int cnt = 0;
void dfs(int node, int parent){
    in[node] = ++cnt;
    anc[0][node] = parent;
    dep[node] = dep[parent] + 1;
    for(auto &x: graph[node]){
        if(x == parent) continue;
        dfs(x, node);
    }
    out[node] = cnt;
}
vector<ll> bit, bit2;
void modify(int pos, ll num){
    while(pos <= n){
        bit[pos] += num;
        pos += (pos & -pos);
    }
}
ll query(int pos){
    ll ans = 0;
    while(pos > 0){
        ans += bit[pos];
        pos -= (pos & -pos);
    }
    return ans;
}
void modify2(int pos, ll num){
    while(pos <= n){
        bit2[pos] += num;
        pos += (pos & -pos);
    }
}
ll query2(int pos){
    ll ans = 0;
    while(pos > 0){
        ans += bit2[pos];
        pos -= (pos & -pos);
    }
    return ans;
}
int lca(int a, int b){
    if(dep[a] < dep[b]) swap(a, b);
    for(int i = 0; i < 18; i++){
        if((dep[a] - dep[b]) & (1 << i)) a = anc[i][a];
    }
    for(int i = 17; i >= 0; i--){
        if(anc[i][a] != anc[i][b]){
            a = anc[i][a];
            b = anc[i][b];
        }
    }
    if(a != b){
        a = anc[0][a];
        b = anc[0][b];
    }
    return a;
}
void add(int l, int r){
    for(int i = l; i <= r; i++){
        ll val = cp[i - 1];
        for(auto &x: pts[i]){
            auto [a, b] = edges[x];
            if(dep[a] < dep[b]) swap(a, b);
            modify(in[a], val);
            if(out[a] < n) modify(out[a] + 1, -val);
            modify2(in[a], -1);
            if(out[a] < n) modify2(out[a] + 1, 1);
        }
    }
}
void rollback(int l, int r){
    for(int i = l; i <= r; i++){
        ll val = cp[i - 1];
        for(auto &x: pts[i]){
            auto [a, b] = edges[x];
            if(dep[a] < dep[b]) swap(a, b);
            modify(in[a], -val);
            if(out[a] < n) modify(out[a] + 1, val);
            modify2(in[a], 1);
            if(out[a] < n) modify2(out[a] + 1, -1); 
        }
    }
}
void f(int l, int r, vector<Query>& queries){
    if(l == r){
        add(l, r);
        for(auto &[s, t, x, y, id]: queries){
            ll ag = query(in[s]) + query(in[t]) - 2 * query(in[lca(s, t)]), au = query2(in[s]) + query2(in[t]) - 2 * query2(in[lca(s, t)]);
            if(ag <= y && au <= x) ans[id] = x - au;
            else ans[id] = -1;
            //cout << id << " " << ag << " " << au << "\n";
        }
        rollback(l, r);
        if(l == 1){
            for(auto &[s, t, x, y, id]: queries){
                ll ag = query(in[s]) + query(in[t]) - 2 * query(in[lca(s, t)]), au = query2(in[s]) + query2(in[t]) - 2 * query2(in[lca(s, t)]);
                if(ans[id] == -1){
                    if(au <= x) ans[id] = x - au;
                }
            }
        }
        return;
    }
    int mid = ((l + r) >> 1) + 1;
    add(l, mid);
    vector<Query> ql, qr;
    for(auto &[s, t, x, y, id]: queries){
        ll ag = query(in[s]) + query(in[t]) - 2 * query(in[lca(s, t)]), au = query2(in[s]) + query2(in[t]) - 2 * query2(in[lca(s, t)]);
        if(ag > y) ql.emplace_back(s, t, x, y, id);
        else qr.emplace_back(s, t, x, y, id);
        //cout << id << " " << mid << " " << ag << " " << au << "\n";
    }
    vector<Query>().swap(queries);
    rollback(mid, mid);
    f(mid, r, qr);
    rollback(l, mid - 1);
    f(l, mid - 1, ql);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> m >> q;
    graph.resize(n + 1);
    pts.resize(m + 1);
    edges.resize(n);
    ans.resize(q);
    anc.resize(18, vector<int>(n + 1));
    in.resize(n + 1);
    out.resize(n + 1);
    dep.resize(n + 1);
    bit2.resize(n + 1);
    bit.resize(n + 1);
    ll a, b;
    for(int i = 1; i < n; i++){
        cin >> a >> b;
        graph[a].push_back(b);
        graph[b].push_back(a);
        edges[i] = make_pair(a, b);
    }
    vector<pair<int, ll>> chktmp;
    for(int i = 1; i <= m; i++){
        cin >> a >> b;
        chktmp.emplace_back(a, b);
        cp.push_back(b);
    }
    sort(cp.begin(), cp.end());
    vector<int> cntt(m + 1);
    for(auto &[id, val]: chktmp){
        val = lower_bound(cp.begin(), cp.end(), val) - cp.begin() + 1;
        cntt[val]++;
        val += cntt[val] - 1;
        pts[val].push_back(id);
    }
    sz = cp.size();
    for(int i = 0; i < q; i++){
        int s, t;
        ll x, y;
        cin >> s >> t >> x >> y;
        queries.emplace_back(s, t, x, y, i);
    }
    dfs(1, 1);
    for(int i = 1; i < 18; i++){
        for(int j = 1; j <= n; j++){
            anc[i][j] = anc[i - 1][anc[i - 1][j]];
        }
    }
    for(int i = 1; i <= sz; i++){
        for(auto &x: pts[i]){
            auto [a, b] = edges[x];
            if(dep[a] < dep[b]) swap(a, b);
            modify2(in[a], 1);
            if(out[a] < n) modify2(out[a] + 1, -1);
        }
    }
    f(1, sz, queries);
    for(int i = 0; i < q; i++) cout << ans[i] << "\n";
}
// g++ -std=gnu++20 pA.cpp -o run -Wall -Wextra -fsanitize=undefined -fsanitize=address

Compilation message (stderr)

currencies.cpp: In function 'void f(int, int, std::vector<Query>&)':
currencies.cpp:118:20: warning: unused variable 'ag' [-Wunused-variable]
  118 |                 ll ag = query(in[s]) + query(in[t]) - 2 * query(in[lca(s, t)]), au = query2(in[s]) + query2(in[t]) - 2 * query2(in[lca(s, t)]);
      |                    ^~
currencies.cpp:130:73: warning: unused variable 'au' [-Wunused-variable]
  130 |         ll ag = query(in[s]) + query(in[t]) - 2 * query(in[lca(s, t)]), au = query2(in[s]) + query2(in[t]) - 2 * query2(in[lca(s, t)]);
      |                                                                         ^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...