2020牛客多校第七场C-A National Pandemic

https://ac.nowcoder.com/acm/contest/5672/C

题意

一棵树,三种操作:

  1. 一个中心城市x,所有城市y的值+=w-dist(x,y);

  2. 将城市x的值与0取min

  3. 询问单点的值。

题解

对于2操作,就相当于对于大于零的点值减去等于点值的数,维护每个点减去的数d[y]即可

关键就在于1操作

对于1操作,我们考虑一次修改(1 x w),对于(y)节点,(y)会增加

[w - dis(x,y)\=w-(dep[x]+dep[y]-dep[lca(x,y)])\=w-dep[x]-dep[y]+2*dep[lca(x,y)] ]

对于w-dep[x]这个部分,直接设一个全局变量totw统计即可

对于dep[y]这个部分,记录一个cnt,每次查询y时减去cnt*dep[y]

对于最后这个部分,我们将x到根加2即可,这样查询时只需要询问y到根的权值和即可获取这部分的值

操作3查询的值即为

[totw-cnt*dep[y]+ask(1,y)-d[y] ]

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
    inline char read() {
    #ifdef _WIN32
        return getchar();
    #endif
        static const int IN_LEN = 1 << 18 | 1;
        static char buf[IN_LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        static char c11, boo;
        for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
            if(c11 == -1) return *this;
            boo |= c11 == '-';
        }
        for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
        boo && (x = -x);
        return *this;
    }
} in;

const int N = 5e4 + 50;
vector<int> G[N];
int n;
/*--------------------------------*/
int cnt;
int fa[N], son[N], sze[N], dep[N];
void dfs1(int u, int f) {
    dep[u] = dep[f] + 1;
    sze[u] = 1;
    fa[u] = f; son[u] = 0;
    for (int v : G[u]) {
        if (v == f) continue;
        dfs1(v, u);
        sze[u] += sze[v]; 
        if (sze[v] > sze[son[u]]) son[u] = v;
    }
}
int top[N], pos[N];
void dfs2(int u, int f, int t) {
    top[u] = t;
    pos[u] = ++cnt;
    if (son[u]) dfs2(son[u], u, t);
    for (int v : G[u]) {
        if (v == f || v == son[u]) continue;
        dfs2(v, u, v);
    }
}
/*--------------------------------*/

/*--------------------------------*/
#define ls (o<<1)
#define rs (o<<1|1)
#define mid ((l+r)>>1)
ll sum[N<<2], add[N<<2];
void pushup(int o) { sum[o] = sum[ls] + sum[rs]; }
void pushdown(int o, int l, int r) {
    if (add[o]) {
        add[ls] += add[o];
        add[rs] += add[o];
        sum[ls] += add[o] * (mid - l + 1);
        sum[rs] += add[o] * (r - mid);
        add[o] = 0;
    }
}
void build(int o, int l, int r) {
    if (l == r) { sum[o] = 0; add[o] = 0; return; }
    sum[o] = 0; add[o] = 0;
    build(ls, l, mid); build(rs, mid + 1, r);
}
void update(int o, int l, int r, int ql, int qr, int v) {
    if (ql <= l && r <= qr) {
        sum[o] += v * (r - l + 1);
        add[o] += v;
        return;
    }
    pushdown(o, l, r);
    if (ql <= mid) update(ls, l, mid, ql, qr, v);
    if (qr > mid) update(rs, mid + 1, r, ql, qr, v);
    pushup(o);
}
ll query(int o, int l, int r, int ql, int qr) {
    if (l == ql && r == qr) { return sum[o]; }
    pushdown(o, l, r);
    if (qr <= mid) return query(ls, l, mid, ql, qr);
    else if (ql > mid) return query(rs, mid + 1, r, ql, qr);
    else return query(ls, l, mid, ql, mid) + query(rs, mid + 1, r, mid + 1, qr);
}
/*--------------------------------*/

/*--------------------------------*/
void change(int u, int v, int val) {
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        update(1, 1, n, pos[top[u]], pos[u], val);
        u = fa[top[u]];
    }
    if (pos[u] < pos[v]) swap(u, v);
    update(1, 1, n, pos[v], pos[u], val);
}
ll ask(int u, int v) {
    ll ans = 0;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans += query(1, 1, n, pos[top[u]], pos[u]);
        u = fa[top[u]];
    }
    if (pos[u] < pos[v]) swap(u, v);
    return ans + query(1, 1, n, pos[v], pos[u]);
}
/*--------------------------------*/
ll totw, cnt1;
ll d[N];
void init() {
    for (int i = 1; i <= n; i++) G[i].clear(), d[i] = 0;
    dep[0] = 0; cnt = 0;
    totw = cnt1 = 0;
    build(1, 1, n);
}
int main() {
    int t; in >> t;
    while (t--) {
        int q; in >> n >> q;
        init();
        for (int i = 1; i < n; i++) {
            int u, v; in >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs1(1, 0);
        dfs2(1, 0, 1);
        while (q--) {
            int op, x; in >> op >> x;
            if (op == 1) {
                int w; in >> w;
                totw += w - dep[x];
                cnt1++;
                change(1, x, 2);
            }
            else if (op == 2) {
                ll v = totw + ask(1, x) - cnt1 * dep[x];
                if (d[x] < v) d[x] = v; 
            }
            else {
                printf("%lld
", totw + ask(1, x) - cnt1 * dep[x] - d[x]);
            }
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/artoriax/p/13632123.html