Submission #1342422

#TimeUsernameProblemLanguageResultExecution timeMemory
1342422dex111222333444555Two Currencies (JOI23_currencies)C++20
100 / 100
593 ms50020 KiB
#include <bits/stdc++.h>
#define all(v) begin(v), end(v)
#define ii pair<int, int>
#define fi first
#define se second
#define siz(v) (int)(v).size()
#define ii pair<int, int>
#define lli pair<long long, int>
#define dbg(x) "[" #x " = " << x << "]"
#define MASK(i) (1LL << (i))

using namespace std;

const int MAXN = 1e5 + 5, infINT = 1e9 + 132123, mod = 998244353, LOG = 18;
const long long inf = 1e18 + 123;

void add(int &a, const int &b){
    a += b;
    if (a >= mod) a -= mod;
}

void sub(int &a, const int &b){
    a -= b;
    if (a < 0) a += mod;
}

int mul(const int &a, const int &b){
    return 1LL * a * 1LL * b % mod;
}

int bin_pow(int a, int k){
    int res = 1;
    while(k){
        if (k & 1) res = mul(res, a);
        k >>= 1; a = mul(a, a);
    }
    return res;
}

template<typename T> struct fenwickTree{
    int n;
    vector<T > bit;

    fenwickTree(int _n = 0): n(_n){
        bit.assign(n + 1, 0);
    }

    void update(int pos, const T &delta){
        for(; pos <= n; pos += pos & -pos) bit[pos] += delta;
    }

    T get(int pos){
        T sum = 0;
        for(; pos > 0; pos ^= pos & -pos) sum += bit[pos];
        return sum;
    }

    void update(int l, int r, const int &delta){
        if (l > r) return;
        update(l, +delta);
        update(r + 1, -delta);
    }

    T get(int l, int r){
        if (l > r) return 0;
        return get(r) - get(l - 1);
    }
};

struct Q{
    int u, v, x;
    long long y;

    Q(int _u = 0, int _v = 0, int _x = 0, long long _y = 0):
        u(_u), v(_v), x(_x), y(_y) {};
};


int numNode, numPos, numQuery, l[MAXN], r[MAXN], m[MAXN], sta[MAXN], fin[MAXN];
int st[LOG][MAXN << 1], tour[MAXN << 1], h[MAXN], rtour[MAXN], cnt[MAXN], res[MAXN];
long long sumCost[MAXN];
vector<int > adj[MAXN], mid[MAXN];
vector<ii > pos;
Q query[MAXN];
fenwickTree<int > bitCnt;
fenwickTree<long long > bitSum;

struct E{
    int u, v;

    E(int _u = 0, int _v = 0):
        u(_u), v(_v) {};

    int other(int x){
        return u ^ v ^ x;
    }

    int high(){
        return h[u] > h[v] ? u: v;
    }
};

E edge[MAXN];

void input(){
    cin >> numNode >> numPos >> numQuery;

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

    for(int i = 1; i <= numPos; i++){
        int p, c; cin >> p >> c;
        pos.emplace_back(c, p);
    }

    for(int q = 1; q <= numQuery; q++){
        int u, v, x;
        long long y;
        cin >> u >> v >> x >> y;
        query[q] = Q(u, v, x, y);
    }
}

void dfs(int u, int par = 0){
    tour[++tour[0]] = u;
    rtour[u] = tour[0];
    sta[u] = ++sta[0];

    for(int id: adj[u]) if (id != par) {
        int v = edge[id].other(u);
        h[v] = h[u] + 1;
        dfs(v, id);
        tour[++tour[0]] = u;
    }

    fin[u] = sta[0];
}

#define minHeight(a, b) (h[a] < h[b] ? a: b)

int lca(int u, int v){
    int l = rtour[u], r = rtour[v];
    if (l > r) swap(l, r);
    int k = __lg(r - l + 1);
    return minHeight(st[k][l], st[k][r - MASK(k) + 1]);
}

int getCnt(int u, int v){
    return bitCnt.get(sta[u]) + bitCnt.get(sta[v]) - 2 * bitCnt.get(sta[lca(u, v)]);
}

long long getSum(int u, int v){
    return bitSum.get(sta[u]) + bitSum.get(sta[v]) - 2 * bitSum.get(sta[lca(u, v)]);
}

void solve(){
    sort(all(pos));
    pos.emplace_back(infINT, numNode + 1);

    dfs(1);
    for(int i = 1; i <= tour[0]; i++) st[0][i] = tour[i];
    for(int j = 1; j < LOG; j++)
    for(int i = 1; i + MASK(j - 1) - 1 <= tour[0]; i++){
        st[j][i] = minHeight(st[j - 1][i], st[j - 1][i + MASK(j - 1)]);
    }

    for(int q = 1; q <= numQuery; q++){
        l[q] = 0, r[q] = siz(pos) - 1;
    }

    fenwickTree<long long > bitSta(numNode);

    for(int i = 0; i < siz(pos); i++){
        int u = edge[pos[i].se].high(), w = pos[i].fi;
        bitSta.update(sta[u], fin[u], +w);
    }

    memset(res, -1, sizeof res);

//    for(int i = 1; i <= numNode; i++) cout << sta[i] << ' '; cout << '\n';

//    for(int u = 1; u <= numNode; u++) cout << bitSta.get(sta[u]) << ' '; cout << '\n';

    int tmp = 0;

    while(true){
        bool flag = 0;

//        cout << "LOOP " << (++tmp) << ": \n";

        for(int q = 1; q <= numQuery; q++) if (l[q] <= r[q]){
            m[q] = (l[q] + r[q]) >> 1;
            flag = 1;
            mid[m[q]].push_back(q);
//            cout << dbg(q) << dbg(m[q])  << '\n';
        }

        if (!flag) break;

        bitCnt = fenwickTree<int >(numNode);
        bitSum = bitSta;

        for(int i = siz(pos) - 1; i >= 0; i--){
//            cout << "I " << i << ": \n";

            int u = edge[pos[i].se].high(), w = pos[i].fi;
            bitSum.update(sta[u], fin[u], -w);
            bitCnt.update(sta[u], fin[u], +1);

//            for(int u = 1; u <= numNode; u++) cout << bitCnt.get(sta[u]) << ' '; cout << '\n';
//            for(int u = 1; u <= numNode; u++) cout << bitSum.get(sta[u]) << ' '; cout << '\n';

            for(int id: mid[i]){
                int u = query[id].u, v = query[id].v, x = query[id].x;
                long long y = query[id].y;
                sumCost[id] = getSum(u, v);
                cnt[id] = getCnt(u, v);
//                cout << "ANS " << u << ' ' << v << ": " << sumCost[id] << ' ' << cnt[id] << '\n';
            }
        }

        for(int q = 1; q <= numQuery; q++) if (l[q] <= r[q]){

            if (sumCost[q] <= query[q].y){
                res[q] = cnt[q];
                l[q] = m[q] + 1;

            }else{
                r[q] = m[q] - 1;

            }

            mid[m[q]].clear();
        }
    }

    for(int q = 1; q <= numQuery; q++) cout << max(-1, query[q].x - res[q]) << '\n';
}

signed main(){
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    #define task "test"
    if (fopen(task".inp", "r")){
        freopen(task".inp", "r", stdin);
        freopen(task".out", "w", stdout);
    }
    input();
    solve();
    cerr << (1.0 * clock()) / CLOCKS_PER_SEC << ".s\n";
}

Compilation message (stderr)

currencies.cpp: In function 'int main()':
currencies.cpp:248:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  248 |         freopen(task".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
currencies.cpp:249:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  249 |         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...