Submission #1353149

#TimeUsernameProblemLanguageResultExecution timeMemory
1353149nagorn_phGrapevine (NOI22_grapevine)C++20
33 / 100
972 ms223552 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

#define ordered_set <int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
#define ordered_multiset <int, null_type, less_equal <int>, rb_tree_tag, tree_order_statistics_node_update>

#define int long long
#define double long double
#define pii pair <int, int>
#define tiii tuple <int, int, int>
#define tiiii tuple <int, int, int, int>
#define emb emplace_back
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define iShowSpeed cin.tie(NULL)->sync_with_stdio(false)
#define matrix vector <vector <int>>
#define mat(n, m) vector <vector <int>> (n, vector <int> (m));

const int mod = 1e9 + 7;
const int inf = 1e18;
const matrix II = {{1, 0}, {0, 1}};
const int N = 1e5 + 5;
const int LG = 20;

int n, q, on[N], sz[N], par[N], depth[N], realdepth[N], tin[N], tout[N], t, dis[LG][N];
bool visited[N];
vector <pii> adj[N], idx[N];

struct segment {
    int sz;
    vector <int> seg, dis, lazy;
    segment() : sz(0) {}
    void push(int l, int r, int i){
        if (seg[i] != inf) seg[i] += lazy[i];
        dis[i] += lazy[i];
        if (l != r) lazy[2 * i] += lazy[i], lazy[2 * i + 1] += lazy[i];
        lazy[i] = 0;
    }
    void build(int l, int r, int i, vector <pii> &node){
        if (l == r) return dis[i] = node[l - 1].second, void();
        int mid = (l + r) / 2;
        build(l, mid, 2 * i, node), build(mid + 1, r, 2 * i + 1, node);
    }
    void initialize(vector <pii> &node){
        sz = node.size();
        seg.resize(4 * sz + 5, inf);
        dis.resize(4 * sz + 5, inf);
        lazy.resize(4 * sz + 5, 0);
        build(1, sz, 1, node);
    }
    void update(int l, int r, int i, int ll, int rr, int val){
        push(l, r, i);
        if (l >= ll && r <= rr) return lazy[i] += val, push(l, r, i), void();
        if (r < ll || l > rr) return;
        int mid = (l + r) / 2;
        update(l, mid, 2 * i, ll, rr, val), update(mid + 1, r, 2 * i + 1, ll, rr, val);
        seg[i] = min(seg[2 * i], seg[2 * i + 1]);
    }
    void open(int l, int r, int i, int idx) {
        push(l, r, i);
        if (l == r) return seg[i] = dis[i], void();
        int mid = (l + r) / 2;
        if (idx <= mid) open(l, mid, 2 * i, idx);
        else open(mid + 1, r, 2 * i + 1, idx);
        seg[i] = min(seg[2 * i], seg[2 * i + 1]);
        dis[i] = min(dis[2 * i], dis[2 * i + 1]);
    }
    void close(int l, int r, int i, int idx){
        push(l, r, i);
        if (l == r) return seg[i] = inf, void();
        int mid = (l + r) / 2;
        if (idx <= mid) close(l, mid, 2 * i, idx);
        else close(mid + 1, r, 2 * i + 1, idx);
        seg[i] = min(seg[2 * i], seg[2 * i + 1]);
        dis[i] = min(dis[2 * i], dis[2 * i + 1]);
    }
    int query(int l, int r, int i, int idx) {
        push(l, r, i);
        if (l == r) return dis[i];
        int mid = (l + r) / 2;
        if (idx <= mid) return query(l, mid, 2 * i, idx);
        return query(mid + 1, r, 2 * i + 1, idx);
    }
};

segment seg[N];

void dfs1(int u, int p){
    tin[u] = ++t;
    realdepth[u] = realdepth[p] + 1;
    for (auto [w, v] : adj[u]) {
        if (v == p || visited[v]) continue;
        dfs1(v, u);
    }
    tout[u] = t;
}

int dfssz(int u, int p){
    sz[u] = 0;
    for (auto [w, v] : adj[u]) {
        if (v == p || visited[v]) continue;
        sz[u] += dfssz(v, u);
    }
    return ++sz[u];
}

int centroid(int u, int p, int szz){
    for (auto [w, v] : adj[u]) {
        if (v == p || visited[v]) continue;
        if (2 * sz[v] > szz) return centroid(v, u, szz);
    }
    return u;
}

void dfs(int u, int p, int dist, vector <pii> &node){
    node.emb(tin[u], dist);
    for (auto [w, v] : adj[u]) {
        if (v == p || visited[v]) continue;
        dfs(v, u, dist + w, node);
    }
}

void decompose(int u, int p){
    int c = centroid(u, u, dfssz(u, u));
    par[c] = p;
    visited[c] = 1;
    depth[c] = depth[p] + 1;
    dfs(c, c, 0, idx[c]);
    sort(all(idx[c]));
    seg[c].initialize(idx[c]);
    for (auto [w, v] : adj[c]) if (!visited[v]) decompose(v, c);
}

map <pii, int> edge;

void update(int u, int v, int w){
    int dif = w - edge[{u, v}];
    edge[{u, v}] = edge[{v, u}] = w;
    if (realdepth[u] > realdepth[v]) swap(u, v);
    int cur = v;
    while (cur) {
        int ll = lower_bound(all(idx[cur]), make_pair(tin[v], -1ll)) - idx[cur].begin() + 1;
        int rr = upper_bound(all(idx[cur]), make_pair(tout[v], inf)) - idx[cur].begin();
        if (tin[v] <= tin[cur] && tout[cur] <= tout[v]) {
            if (ll > 1) seg[cur].update(1, seg[cur].sz, 1, 1, ll - 1, dif);
            if (rr < seg[cur].sz) seg[cur].update(1, seg[cur].sz, 1, rr + 1, seg[cur].sz, dif);
        }
        else if (ll <= rr) seg[cur].update(1, seg[cur].sz, 1, ll, rr, dif);
        cur = par[cur];
    }
}

void open(int u){
    int v = u;
    while (v) {
        int idxx = lower_bound(all(idx[v]), make_pair(tin[u], -1ll)) - idx[v].begin() + 1;
        seg[v].open(1, seg[v].sz, 1, idxx);
        v = par[v];
    }
}

void close(int u){
    int v = u;
    while (v) {
        int idxx = lower_bound(all(idx[v]), make_pair(tin[u], -1ll)) - idx[v].begin() + 1;
        seg[v].close(1, seg[v].sz, 1, idxx);
        v = par[v];
    }
}

int query(int u){
    int v = u;
    int ans = inf;
    while (v) {
        int idxx = lower_bound(all(idx[v]), make_pair(tin[u], -1ll)) - idx[v].begin() + 1;
        ans = min(ans, seg[v].query(1, seg[v].sz, 1, idxx) + seg[v].seg[1]);
        v = par[v];
    }
    return ans;
}

void solve(){
    cin >> n >> q;
    for (int i = 1; i < n; i++) {
        int u, v, w; cin >> u >> v >> w;
        adj[u].emb(w, v);
        adj[v].emb(w, u);
        edge[{u, v}] = edge[{v, u}] = w;
    }
    dfs1(1, 1);
    decompose(1, 0);
    while (q--) {
        int t; cin >> t;
        if (t == 2) {
            int u; cin >> u;
            if (on[u]) on[u] = 0, close(u);
            else on[u] = 1, open(u);
        }
        if (t == 1) {
            int u; cin >> u;
            int ans = query(u);
            cout << (ans >= inf ? -1ll : ans) << "\n";
        }
        if (t == 3) {
            int u, v, w; cin >> u >> v >> w;
            update(u, v, w);
        }
    }
}

int32_t main(){
    iShowSpeed;
    // int q; cin >> q; while (q--) 
    solve();
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...