Submission #1292622

#TimeUsernameProblemLanguageResultExecution timeMemory
1292622MinbaevFactories (JOI14_factories)C++20
0 / 100
21 ms788 KiB
#include "factories.h"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;

struct Seg {
    int n;
    vector<ll> tree, lazy;
    Seg(): n(0) {}
    Seg(int n_){ init(n_); }
    void init(int n_){
        n = n_;
        tree.assign(4*n+5, 0);
        lazy.assign(4*n+5, LLONG_MAX);
    }
    inline void apply(int v, int l, int r, ll val){
        tree[v] = val * (r - l + 1);
        lazy[v] = val;
    }
    inline void push(int v, int l, int r){
        if(lazy[v]==LLONG_MAX) return;
        if(l!=r){
            int m=(l+r)>>1;
            apply(v<<1, l, m, lazy[v]);
            apply(v<<1|1, m+1, r, lazy[v]);
        }
        lazy[v]=LLONG_MAX;
    }
    void upd(int v,int l,int r,int ql,int qr,ll val){
        if(ql>qr || r<ql || qr<l) return;
        if(ql<=l && r<=qr){ apply(v,l,r,val); return; }
        push(v,l,r);
        int m=(l+r)>>1;
        upd(v<<1,l,m,ql,qr,val);
        upd(v<<1|1,m+1,r,ql,qr,val);
        tree[v]=tree[v<<1]+tree[v<<1|1];
    }
    ll get(int v,int l,int r,int ql,int qr){
        if(ql>qr || r<ql || qr<l) return 0;
        if(ql<=l && r<=qr) return tree[v];
        push(v,l,r);
        int m=(l+r)>>1;
        return get(v<<1,l,m,ql,qr)+get(v<<1|1,m+1,r,ql,qr);
    }
    void range_assign(int l,int r,int val){ if(l>r) return; upd(1,1,n,l,r,(ll)val); }
    ll range_sum(int l,int r){ if(l>r) return 0; return get(1,1,n,l,r); }
};

static int Nglob = 0;
static vector<vector<pair<int,int>>> g;
static vector<int> parent_v, sz_v, idv, id_rev, head;
static vector<ll> dep;
static int timer_;
static Seg seg;

void dfs(int u,int p){
    parent_v[u]=p;
    sz_v[u]=1;
    for(auto &e: g[u]){
        int v=e.first, w=e.second;
        if(v==p) continue;
        dep[v]=dep[u]+(ll)w;
        dfs(v,u);
        sz_v[u]+=sz_v[v];
    }
}

void hld(int u,int p){
    int heavy=-1;
    for(auto &e: g[u]){
        int v=e.first;
        if(v==p) continue;
        if(heavy==-1 || sz_v[v]>sz_v[heavy]) heavy=v;
    }
    timer_++;
    idv[u]=timer_;
    id_rev[timer_]=u;
    if(heavy!=-1){
        head[heavy]=head[u];
        hld(heavy,u);
    }
    for(auto &e: g[u]){
        int v=e.first;
        if(v==p || v==heavy) continue;
        head[v]=v;
        hld(v,u);
    }
}

int up_node(int x){
    while(true){
        int h=head[x];
        int hid=idv[h], xid=idv[x];
        if(hid+1 <= xid){
            ll ones = seg.range_sum(hid+1, xid);
            ll need = (ll)(xid - hid);
            if(ones == need){
                if(parent_v[h]==-1) return h;
                x = parent_v[h];
                continue;
            } else {
                int L = hid+1, R = xid;
                while(L < R){
                    int M = (L + R) >> 1;
                    ll s = seg.range_sum(M, xid);
                    ll need2 = (ll)(xid - M + 1);
                    if(s == need2) R = M;
                    else L = M + 1;
                }
                int topnode = id_rev[L-1];
                return topnode;
            }
        } else {
            if(parent_v[h]==-1) return h;
            x = parent_v[h];
            continue;
        }
    }
}

void set_path_up(int x,int val){
    while(true){
        int h=head[x];
        int hid=idv[h], xid=idv[x];
        if(hid+1 <= xid) seg.range_assign(hid+1, xid, val);
        if(parent_v[h]==-1) break;
        x = parent_v[h];
    }
}

void Init(int N, int A[], int B[], int D[]){
    Nglob = N;
    g.assign(Nglob, {});
    parent_v.assign(Nglob, -1);
    sz_v.assign(Nglob, 0);
    idv.assign(Nglob, 0);
    id_rev.assign(Nglob+1, 0);
    head.assign(Nglob, 0);
    dep.assign(Nglob, 0);
    timer_ = 0;
    for(int i=0;i<Nglob-1;i++){
        int a=A[i], b=B[i], d=D[i];
        g[a].push_back({b,d});
        g[b].push_back({a,d});
    }
    dep[0]=0;
    dfs(0,-1);
    head[0]=0;
    hld(0,-1);
    seg.init(Nglob);
}

long long Query(int S, int X[], int T, int Y[]){
    for(int i=0;i<S;i++) set_path_up(X[i], 1);
    vector<pair<int,ll>> vs; vs.reserve(T);
    for(int i=0;i<T;i++){
        int y=Y[i];
        int u = up_node(y);
        ll dist = dep[y] - dep[u];
        vs.emplace_back(u, dist);
    }
    for(int i=0;i<S;i++) set_path_up(X[i], 0);
    unordered_map<int,ll> best;
    best.reserve(vs.size()*2+3);
    for(auto &pr: vs){
        int u=pr.first; ll d=pr.second;
        auto it = best.find(u);
        if(it==best.end()) best[u]=d;
        else if(d < it->second) it->second = d;
    }
    for(auto &kv: best){
        int u = kv.first;
        ll val = kv.second;
        seg.range_assign(idv[u], idv[u], (int)val);
    }
    ll ans = LLONG_MAX;
    for(int i=0;i<S;i++){
        int x = X[i];
        int u = up_node(x);
        ll cell = seg.range_sum(idv[u], idv[u]);
        if(cell==0) continue;
        ll cand = (dep[x] - dep[u]) + cell;
        if(cand < ans) ans = cand;
    }
    for(auto &kv: best){
        seg.range_assign(idv[kv.first], idv[kv.first], 0);
    }
    if(ans==LLONG_MAX) return -1;
    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...