Submission #1346538

#TimeUsernameProblemLanguageResultExecution timeMemory
1346538nguyenkhangninh99Grapevine (NOI22_grapevine)C++20
100 / 100
740 ms211652 KiB
#include<bits/stdc++.h>
using namespace std;

#define int long long
const int maxn = 1e5 + 5;
const int INF = 1e15;

struct Seg {
    int n;
    vector<int> mn, dist, lz;
    void init(int sz) {
        n = sz;
        mn.assign(4 * n + 5, INF);
        dist.assign(4 * n + 5, 0);
        lz.assign(4 * n + 5, 0);
    }
    void build(int id, int l, int r, vector<int>& a) {
        if(l == r) { dist[id] = a[l]; return; }
        int mid = (l + r) / 2;
        build(id * 2, l, mid, a);
        build(id * 2 + 1, mid + 1, r, a);
        dist[id] = min(dist[id * 2], dist[id * 2 + 1]); 
    }
    void down(int id) {
        if(!lz[id]) return;
        for(int i = 0; i < 2; i++) {
            int c = id * 2 + i;
            if(mn[c] < INF / 2) mn[c] += lz[id];
            dist[c] += lz[id];
            lz[c] += lz[id];
        }
        lz[id] = 0;
    }
    void up_range(int id, int l, int r, int u, int v, int val) {
        if(l > v || r < u) return;
        if(u <= l && r <= v) {
            if(mn[id] < INF / 2) mn[id] += val;
            dist[id] += val;
            lz[id] += val;
            return;
        }
        down(id);
        int mid = (l + r) / 2;
        up_range(id * 2, l, mid, u, v, val);
        up_range(id * 2 + 1, mid + 1, r, u, v, val);
        mn[id] = min(mn[id * 2], mn[id * 2 + 1]);
        dist[id] = min(dist[id * 2], dist[id * 2 + 1]);
    }
    void up_point(int id, int l, int r, int p, int has) {
        if(l == r) {
            mn[id] = has ? dist[id] : INF;
            return;
        }
        down(id);
        int mid = (l + r) / 2;
        if(p <= mid) up_point(id * 2, l, mid, p, has);
        else up_point(id * 2 + 1, mid + 1, r, p, has);
        mn[id] = min(mn[id * 2], mn[id * 2 + 1]);
    }
    int get_dist(int id, int l, int r, int p) {
        if(l == r) return dist[id];
        down(id);
        int mid = (l + r) / 2;
        if(p <= mid) return get_dist(id * 2, l, mid, p);
        return get_dist(id * 2 + 1, mid + 1, r, p);
    }
};

vector<array<int, 2>> g[maxn];
int sz[maxn], del[maxn], par[maxn], lvl[maxn];
int tin[20][maxn], tout[20][maxn], timer[maxn];
Seg st[maxn];

int get_sz(int u, int p) {
    sz[u] = 1;
    for(auto [v, w] : g[u]) {
        if(v != p && !del[v]) sz[u] += get_sz(v, u);
    }
    return sz[u];
}

int centroid(int u, int p, int targ) {
    for(auto [v, w] : g[u]) {
        if(v != p && !del[v] && sz[v] > targ / 2) return centroid(v, u, targ);
    }
    return u;
}

void dfs_comp(int u, int p, int d, int l, int c, vector<int>& init_d) {
    tin[l][u] = ++timer[c];
    init_d.push_back(d);
    for(auto [v, w] : g[u]) {
        if(v != p && !del[v]) dfs_comp(v, u, d + w, l, c, init_d);
    }
    tout[l][u] = timer[c];
}

void decompose(int u, int p, int l) {
    u = centroid(u, -1, get_sz(u, -1));
    del[u] = 1;
    par[u] = p;
    lvl[u] = l;

    vector<int> init_d;
    init_d.push_back(0); 
    timer[u] = 0;
    dfs_comp(u, -1, 0, l, u, init_d);

    st[u].init(timer[u]);
    st[u].build(1, 1, timer[u], init_d);

    for(auto [v, w] : g[u]) {
        if(!del[v]) decompose(v, u, l + 1);
    }
}

signed main() {
    ios_base::sync_with_stdio(0); cin.tie(0);
    
    int n, q; cin >> n >> q;
    map<pair<int, int>, int> ew;
    
    for(int i = 1; i < n; i++) {
        int u, v, w; cin >> u >> v >> w;
        g[u].push_back({v, w});
        g[v].push_back({u, w});
        ew[{min(u, v), max(u, v)}] = w;
    }

    decompose(1, 0, 1);
    vector<int> at(n + 1, 0);

    while(q--) {
        int type; cin >> type;
        if(type == 1) {
            int x; cin >> x;
            int ans = INF, cur = x;
            while(cur) {
                int l = lvl[cur];
                int d = st[cur].get_dist(1, 1, st[cur].n, tin[l][x]);
                ans = min(ans, d + st[cur].mn[1]);
                cur = par[cur];
            }
            cout << (ans >= INF / 2 ? -1 : ans) << "\n";
        } 
        else if(type == 2) {
            int x; cin >> x;
            at[x] ^= 1;
            int cur = x;
            while(cur) {
                int l = lvl[cur];
                st[cur].up_point(1, 1, st[cur].n, tin[l][x], at[x]);
                cur = par[cur];
            }
        } 
        else {
            int u, v, w; cin >> u >> v >> w;
            int delta = w - ew[{min(u, v), max(u, v)}];
            ew[{min(u, v), max(u, v)}] = w;

            vector<int> pu, pv;
            int cu = u; while(cu) { pu.push_back(cu); cu = par[cu]; }
            int cv = v; while(cv) { pv.push_back(cv); cv = par[cv]; }

            int i = pu.size() - 1, j = pv.size() - 1;
            while(i >= 0 && j >= 0 && pu[i] == pv[j]) {
                int c = pu[i];
                int l = lvl[c];
                int child = (tin[l][u] > tin[l][v]) ? u : v;
                st[c].up_range(1, 1, st[c].n, tin[l][child], tout[l][child], delta);
                i--; j--;
            }
        }
    }
    return 0;
}
#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...