제출 #1282005

#제출 시각아이디문제언어결과실행 시간메모리
1282005ducdevGrapevine (NOI22_grapevine)C++17
0 / 100
844 ms134384 KiB
// Author: 4uckd3v - Nguyen Cao Duc
#include <bits/stdc++.h>
using namespace std;

#define all(x) (x).begin(), (x).end()

typedef long long ll;
typedef pair<int, int> ii;

const int MAX_N = 1e5;
const int MOD = 1e9 + 7;
const ll INF = 1e18;

struct SegmentTree {
    vector<ll> seg, lazy;
    int n;

    void down(int node) {
        for (int i = 0; i < 2; i++) {
            seg[node << 1 | i] += lazy[node];
            lazy[node << 1 | i] += lazy[node];
        };
        lazy[node] = 0;
    };

    void assign(int pos, ll val) {
        int l = 1, r = n, node = 1;

        while (l < r) {
            int mid = (l + r) >> 1;
            if (lazy[node]) down(node);

            if (pos <= mid) {
                node <<= 1;
                r = mid;
            } else {
                (node <<= 1) |= 1;
                l = mid + 1;
            };
        };

        seg[node] = val;
        while (node > 1) {
            node >>= 1;
            seg[node] = min(seg[node << 1], seg[node << 1 | 1]);
        };
    };

    void update(int node, int l, int r, int u, int v, int val) {
        if (l > v || r < u) return;

        if (l >= u && r <= v) {
            seg[node] += val;
            lazy[node] += val;
            return;
        };

        int mid = (l + r) >> 1;
        if (lazy[node]) down(node);

        update(node << 1, l, mid, u, v, val);
        update(node << 1 | 1, mid + 1, r, u, v, val);

        seg[node] = min(seg[node << 1], seg[node << 1 | 1]);
    };

    void update(int l, int r, int val) {
        update(1, 1, n, l, r, val);
    };

    ll getMin() {
        return seg[1];
    };

    SegmentTree() {};
    SegmentTree(int n) : n(n) {
        seg.assign(4 * n + 5, INF);
        lazy.assign(4 * n + 5, 0);
    };
};

struct FenwickTree {
    int n;
    vector<ll> bit;

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

    ll get(int pos) {
        ll ret = 0;
        for (; pos > 0; pos -= pos & (-pos))
            ret += bit[pos];
        return ret;
    };

    FenwickTree() {};
    FenwickTree(int n) : n(n) {
        bit.assign(n + 5, 0);
    };
};

int n, q, timer, lg;
int par[MAX_N + 5], sz[MAX_N + 5], tin[MAX_N + 5], tout[MAX_N + 5], edgeWeight[MAX_N + 5];
int up[MAX_N + 5][18];
bool del[MAX_N + 5], grap[MAX_N + 5];
ll f[MAX_N + 5];
vector<int> centNode[MAX_N + 5];
vector<ii> adj[MAX_N + 5];
SegmentTree seg[MAX_N + 5];
FenwickTree bit;

void preDfs(int u, int p) {
    tin[u] = ++timer;
    up[u][0] = p;

    for (int i = 1; i <= lg; i++)
        up[u][i] = up[up[u][i - 1]][i - 1];

    for (ii e : adj[u]) {
        int v = e.first, w = e.second;
        if (v == p) continue;
        edgeWeight[v] = w;
        f[v] = f[u] + w;
        preDfs(v, u);
    };

    tout[u] = timer;
};

bool isAncestor(int u, int v) {
    return tin[u] <= tin[v] && tout[u] >= tout[v];
};

int __lca(int u, int v) {
    if (isAncestor(u, v)) return u;
    if (isAncestor(v, u)) return v;

    for (int i = lg; i >= 0; i--)
        if (!isAncestor(up[u][i], v))
            u = up[u][i];

    return up[u][0];
};

ll dist(int u, int v) {
    return f[u] + f[v] - f[__lca(u, v)] * 2;
};

void calcSize(int u, int p) {
    sz[u] = 1;
    for (ii e : adj[u]) {
        int v = e.first;
        if (v == p || del[v]) continue;
        calcSize(v, u);
        sz[u] += sz[v];
    };
};

int findCentroid(int u, int p, int n) {
    for (ii e : adj[u]) {
        int v = e.first;
        if (v == p || del[v]) continue;
        if (sz[v] * 2 > n) return findCentroid(v, u, n);
    };
    return u;
};

void collectNode(int root, int u, int p) {
    centNode[root].push_back(u);
    for (ii e : adj[u]) {
        int v = e.first;
        if (v == p || del[v]) continue;
        collectNode(root, v, u);
    };
};

void decompose(int u, int p) {
    calcSize(u, u);

    int centroid = findCentroid(u, u, sz[u]);
    par[centroid] = p;
    del[centroid] = true;

    collectNode(centroid, centroid, centroid);

    sort(all(centNode[centroid]), [&](int u, int v) {
        return tin[u] < tin[v];
    });

    for (ii e : adj[centroid]) {
        int v = e.first;
        if (del[v]) continue;
        decompose(v, centroid);
    };
};

ll sumPath(int u, int v) {
    return bit.get(tin[u]) + bit.get(tin[v]) - bit.get(tin[__lca(u, v)]) * 2;
};

ll query(int u) {
    ll res = INF;

    for (int v = u; v != 0; v = par[v]) {
        res = min(res, sumPath(u, v) + seg[v].getMin());
    };

    return res;
};

int findLeft(int x, const vector<int>& data) {
    int l = 0, r = (int)data.size() - 1, pos = -1;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (tin[data[mid]] >= x) {
            pos = mid;
            r = mid - 1;
        } else
            l = mid + 1;
    };
    return pos;
};

int findRight(int x, const vector<int>& data) {
    int l = 0, r = (int)data.size() - 1, pos = -1;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (tin[data[mid]] <= x) {
            pos = mid;
            l = mid + 1;
        } else
            r = mid - 1;
    };
    return pos;
};

void updateGrap(int u) {
    grap[u] ^= 1;

    for (int v = u; v != 0; v = par[v]) {
        int idx = findLeft(tin[u], centNode[v]) + 1;
        ll val = grap[u] ? sumPath(u, v) : INF;
        seg[v].assign(idx, val);
    };
};

void updateWeight(int u, int delta) {
    for (int v = par[u]; v != 0; v = par[v]) {
        int l = findLeft(tin[u], centNode[v]) + 1;
        if (l == 0) continue;
        int r = findRight(tout[u], centNode[v]) + 1;
        seg[v].update(l, r, delta);
    };
};

int main() {
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    if (fopen("MAIN.INP", "r")) {
        freopen("MAIN.INP", "r", stdin);
        freopen("MAIN.OUT", "w", stdout);
    };

    cin >> n >> q;
    for (int i = 1; i < n; i++) {
        int u, v, w;
        cin >> u >> v >> w;
        adj[u].push_back(ii(v, w));
        adj[v].push_back(ii(u, w));
    };

    lg = ceil(log2(n));
    preDfs(1, 1);
    decompose(1, 0);

    int cntGrap = 0;

    for (int u = 1; u <= n; u++) {
        seg[u] = SegmentTree(centNode[u].size());
    };

    bit = FenwickTree(n);
    for (int u = 2; u <= n; u++) {
        bit.update(tin[u], edgeWeight[u]);
        bit.update(tout[u] + 1, -edgeWeight[u]);
    };

    while (q--) {
        int type, u;
        cin >> type >> u;
        if (type == 1) {
            cout << (cntGrap == 0 ? -1 : query(u)) << '\n';
        };

        if (type == 2) {
            cntGrap += (grap[u] ? -1 : 1);
            updateGrap(u);
        };

        if (type == 3) {
            int v, newWeight;
            cin >> v >> newWeight;
            if (isAncestor(v, u)) swap(u, v);

            int delta = -edgeWeight[v] + newWeight;

            bit.update(tin[v], delta);
            bit.update(tout[v] + 1, -delta);

            updateWeight(v, delta);

            edgeWeight[v] = newWeight;
        };
    };
};

컴파일 시 표준 에러 (stderr) 메시지

Main.cpp: In function 'int main()':
Main.cpp:262:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  262 |         freopen("MAIN.INP", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:263:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  263 |         freopen("MAIN.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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...