zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    饿了么P7级前端工程师进入大厂的面试经验
    前端程序员面试的坑,简历写上这一条信息会被虐死!
    这次来分享前端的九条bug吧
    移动端开发必会出现的问题和解决方案
    创建一个dynamics 365 CRM online plugin (八)
    创建一个dynamics 365 CRM online plugin (七)
    创建一个dynamics 365 CRM online plugin (六)
    创建一个dynamics 365 CRM online plugin (五)
    使用User Primary Email作为GUID的问题
    怎样Debug Dynamics 365 CRM Plugin
  • 原文地址:https://www.cnblogs.com/artoriax/p/13632123.html
Copyright © 2011-2022 走看看