Submission #1302073

#TimeUsernameProblemLanguageResultExecution timeMemory
1302073regulardude6Tree (IOI24_tree)C++20
7 / 100
83 ms34244 KiB
#include "tree.h"
#include <bits/stdc++.h>
using namespace std;

using ll = long long;

struct DSU {
    vector<int> p, sz;
    vector<int> leaves;
    vector<ll> mn;
    DSU(int n): p(n), sz(n,1), leaves(n,0), mn(n,0) { iota(p.begin(), p.end(), 0); }
    int find(int x){ while(p[x]!=x){ p[x]=p[p[x]]; x=p[x]; } return x; }
    int unite(int a,int b){
        a=find(a); b=find(b);
        if(a==b) return a;
        if(sz[a]<sz[b]) swap(a,b);
        p[b]=a;
        sz[a]+=sz[b];
        leaves[a]+=leaves[b];
        mn[a]=min(mn[a], mn[b]);
        return a;
    }
};

static int N;
static vector<int> P;
static vector<ll> W;
static vector<vector<int>> ch;
static vector<char> isLeaf, active;
static ll leafSum;
static int totalLeaves;

static vector<pair<int,ll>> ev;
static vector<ll> prefD, prefKD;

void init(vector<int> _P, vector<int> _W) {
    P = _P;
    N = (int)P.size();
    W.assign(N, 0);
    for(int i=0;i<N;i++) W[i] = (ll)_W[i];

    ch.assign(N, {});
    int root = 0;
    for(int i=0;i<N;i++){
        if(P[i] == -1) root = i;
        else ch[P[i]].push_back(i);
    }

    isLeaf.assign(N, 0);
    leafSum = 0;
    totalLeaves = 0;
    for(int i=0;i<N;i++){
        if(ch[i].empty()){
            isLeaf[i] = 1;
            leafSum += W[i];
            totalLeaves++;
        }
    }

    active.assign(N, 0);
    DSU dsu(N);

    for(int i=0;i<N;i++){
        if(isLeaf[i]){
            active[i] = 1;
            dsu.leaves[i] = 1;
            dsu.mn[i] = 0;
        }
    }

    vector<int> internal;
    internal.reserve(N);
    for(int i=0;i<N;i++) if(!isLeaf[i]) internal.push_back(i);
    sort(internal.begin(), internal.end(), [&](int a,int b){
        if(W[a] != W[b]) return W[a] > W[b];
        return a < b;
    });

    ev.clear();
    ev.reserve(2LL*N);

    auto add_ev = [&](int k, ll d){
        if(k <= 0) return;
        if(d == 0) return;
        ev.push_back({k, d});
    };

    for(int v: internal){
        ll wv = W[v];
        active[v] = 1;
        dsu.leaves[v] = 0;
        dsu.mn[v] = wv;

        int r = dsu.find(v);

        add_ev(dsu.leaves[r], -dsu.mn[r]);

        vector<int> roots;
        roots.reserve(ch[v].size() + 1);

        if(P[v] != -1 && active[P[v]]) roots.push_back(dsu.find(P[v]));
        for(int u: ch[v]) if(active[u]) roots.push_back(dsu.find(u));

        sort(roots.begin(), roots.end());
        roots.erase(unique(roots.begin(), roots.end()), roots.end());

        for(int rr: roots){
            rr = dsu.find(rr);
            r = dsu.find(r);
            if(rr == r) continue;
            add_ev(dsu.leaves[rr], -dsu.mn[rr]);
            r = dsu.unite(r, rr);
        }

        r = dsu.find(v);
        dsu.mn[r] = wv;
        add_ev(dsu.leaves[r], +dsu.mn[r]);
    }

    sort(ev.begin(), ev.end(), [&](auto &a, auto &b){
        if(a.first != b.first) return a.first < b.first;
        return a.second < b.second;
    });

    int m = (int)ev.size();
    prefD.assign(m+1, 0);
    prefKD.assign(m+1, 0);
    for(int i=0;i<m;i++){
        prefD[i+1] = prefD[i] + ev[i].second;
        prefKD[i+1] = prefKD[i] + (ll)ev[i].first * ev[i].second;
    }
}

long long query(int L, int R) {
    ll LL = (ll)L, RR = (ll)R;
    ll T = (RR + LL - 1) / LL;
    if(T <= 1) T = 1;
    if(T > totalLeaves + 1) return leafSum * LL;

    int m = (int)ev.size();
    int idx = lower_bound(ev.begin(), ev.end(), make_pair((int)T, (ll)-4e18),
                          [&](const pair<int,ll>& a, const pair<int,ll>& b){
                              if(a.first != b.first) return a.first < b.first;
                              return a.second < b.second;
                          }) - ev.begin();

    ll sufD = prefD[m] - prefD[idx];
    ll sufKD = prefKD[m] - prefKD[idx];

    return leafSum * LL + sufKD * LL - sufD * RR;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...