zoukankan      html  css  js  c++  java
  • HDU

    HDU - 6104

    非常恶心的一道题, 维护的东西和幻想乡战略游戏差不多, 不过不同的是它的边权会变,

    并且一个操作的贡献不会因为边权的改变而改变, 我们先考虑改变边权的时候不改变d1, d2数组,

    那么在query进行u 和 fa[u]合并的时候, 那个边权会多加东西, 我们考虑改变边权的时候把多加的减掉就ok了, 

    也就是多维护一个del 的 树状数组。

    #pragma GCC optimize(2)
    #pragma GCC optimize(3)
    #include<bits/stdc++.h>
    #define LL long long
    #define LD long double
    #define ull unsigned long long
    #define fi first
    #define se second
    #define mk make_pair
    #define PLL pair<LL, LL>
    #define PLI pair<LL, int>
    #define PII pair<int, int>
    #define SZ(x) ((int)x.size())
    #define ALL(x) (x).begin(), (x).end()
    #define fio ios::sync_with_stdio(false); cin.tie(0);
    
    using namespace std;
    
    const int N = 2e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = (int)1e9 + 7;
    const double eps = 1e-8;
    const double PI = acos(-1);
    
    template<class T, class S> inline void add(T& a, S b) {a += b; if(a >= mod) a -= mod;}
    template<class T, class S> inline void sub(T& a, S b) {a -= b; if(a < 0) a += mod;}
    template<class T, class S> inline bool chkmax(T& a, S b) {return a < b ? a = b, true : false;}
    template<class T, class S> inline bool chkmin(T& a, S b) {return a > b ? a = b, true : false;}
    
    //mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    
    const int LOG = 20;
    
    int n, q;
    vector<int> G[N];
    
    int pa[N];
    int w[N];
    int depth[N];
    int dfn[N];
    int rmq_cnt;
    int Log[N];
    PII rmq[N][LOG];
    
    int es[N];
    
    struct Bit {
        int n;
        vector<int> a;
        void init(int _n) {
            n = _n;
            a.resize(n + 1);
            for(int i = 0; i <= n; i++) {
                a[i] = 0;
            }
        }
        inline void modify(int x, int v) {
            for(int i = x; i <= n; i += i & -i) {
                a[i] += v;
            }
        }
        inline int sum(int x) {
            int ans = 0;
            for(int i = x; i; i -= i & -i) {
                ans += a[i];
            }
            return ans;
        }
        inline int query(int L, int R) {
            if(L > R) return 0;
            return sum(R) - sum(L - 1);
        }
    } bit, B[N], del[N];
    
    void dfs(int u, int fa) {
        dfn[u] = ++rmq_cnt;
        rmq[rmq_cnt][0] = mk(depth[u], u);
        for(auto &v : G[u]) {
            if(v == fa) continue;
            bit.modify(rmq_cnt + 1, 1);
            es[v * 2] = rmq_cnt + 1;
            depth[v] = depth[u] + 1;
            dfs(v, u);
            rmq[++rmq_cnt][0] = mk(depth[u], u);
            bit.modify(rmq_cnt + 1, -1);
            es[v * 2 + 1] = rmq_cnt + 1;
        }
    }
    
    void calcRmq() {
        for(int i = 2; i <= rmq_cnt; i++) {
            Log[i] = Log[i >> 1] + 1;
        }
        for(int j = 1; j <= Log[rmq_cnt]; j++) {
            for(int i = 1; i + (1 << j) - 1 <= rmq_cnt; i++) {
                rmq[i][j] = min(rmq[i][j - 1], rmq[i + (1 << (j - 1))][j - 1]);
            }
        }
    }
    
    int getLca(int u, int v) {
        if(dfn[u] > dfn[v]) swap(u, v);
        int k = Log[dfn[v] - dfn[u] + 1];
        PII ret = min(rmq[dfn[u]][k], rmq[dfn[v] - (1 << k) + 1][k]);
        return ret.se;
    }
    
    int getDis(int u, int v) {
        int lca = getLca(u, v);
        return bit.sum(dfn[u]) + bit.sum(dfn[v]) - 2 * bit.sum(dfn[lca]);
    }
    
    int sz[N], mx[N], fa[N];
    int center, now_tot;
    bool ban[N];
    
    void getSize(int u, int fa) {
        sz[u] = 1;
        for(auto &v : G[u]) {
            if(v == fa || ban[v]) continue;
            getSize(v, u);
            sz[u] += sz[v];
        }
    }
    
    void findCenter(int u, int fa) {
        mx[u] = 0;
        for(auto &v : G[u]) {
            if(v == fa || ban[v]) continue;
            findCenter(v, u);
            chkmax(mx[u], sz[v]);
        }
        chkmax(mx[u], now_tot - sz[u]);
        if(mx[center] > mx[u]) {
            center = u;
        }
    }
    
    int idx;
    int dep[N];
    int in[20][N], ot[20][N], fr[20][N];
    
    LL sum[N], d1[N], d2[N];
    
    void dfs(int u, int fa, int rt, int *in, int *ot, int *fr) {
        in[u] = ++idx;
        fr[u] = fa == rt ? u : fr[fa];
        for(auto &v : G[u]) {
            if(v == fa || ban[v]) continue;
            dfs(v, u, rt, in, ot, fr);
        }
        ot[u] = idx;
    }
    
    void divide(int u) {
        dfs(u, idx = 0, u, in[dep[u]], ot[dep[u]], fr[dep[u]]);
        B[u].init(idx);
        del[u].init(idx);
        ban[u] = true;
        for(auto &v : G[u]) {
            if(ban[v]) continue;
    
            getSize(v, 0);
            center = 0; now_tot = sz[v];
            findCenter(v, 0);
            fa[center] = u;
            dep[center] = dep[u] + 1;
    
            divide(center);
        }
    }
    
    void modifyEdge(int u, int v, int w) {
        int delVal = -w;
        bit.modify(es[v * 2], w);
        bit.modify(es[v * 2 + 1], -w);
        if(dep[u] > dep[v]) swap(u, v);
        for(int cur = u; cur; cur = fa[cur]) {
            int d = dep[cur];
            int pos = in[d][u] > in[d][v] ? u : v;
            int top = fr[d][pos];
            LL tmp = B[cur].query(1, in[d][top] - 1) + B[cur].query(ot[d][top] + 1, B[cur].n);
            del[cur].modify(in[d][pos], delVal * tmp);
            del[cur].modify(ot[d][pos] + 1, -delVal * tmp);
        }
    }
    
    void modifyPoint(int x, int w) {
        for(int cur = x; cur; cur = fa[cur]) {
            sum[cur] += w;
            B[cur].modify(in[dep[cur]][x], w);
            if(fa[cur]) {
                LL dis = 1LL * w * getDis(fa[cur], x);
                d2[cur] += dis;
                d1[fa[cur]] += dis;
            }
        }
    }
    
    inline LL query(int x) {
        LL ans = d1[x];
        for(int cur = x; fa[cur]; cur = fa[cur]) {
            ans += d1[fa[cur]];
            ans -= d2[cur];
            ans += (sum[fa[cur]] - sum[cur]) * getDis(x, fa[cur]);
            ans += del[fa[cur]].sum(in[dep[fa[cur]]][x]);
        }
        return ans;
    }
    
    void init() {
        rmq_cnt = 0;
        for(int i = 1; i <= n; i++) {
            G[i].clear();
            w[i] = 0;
            ban[i] = false;
            sum[i] = d1[i] = d2[i] = fa[i] = 0;
        }
    }
    
    int main() {
        int T; scanf("%d", &T);
        while(T--) {
            scanf("%d", &n);
            init();
            for(int i = 2; i <= n; i++) {
                scanf("%d", &pa[i]);
                w[i] = 1;
                G[pa[i]].push_back(i);
                G[i].push_back(pa[i]);
            }
    
            bit.init(2 * n - 1);
            dfs(1, 0);
            calcRmq();
    
    
            mx[0] = inf;
            getSize(1, 0);
            center = 0; now_tot = sz[1];
            findCenter(1, 0);
    
            dep[center] = 1;
            divide(center);
    
            scanf("%d", &q);
    
            while(q--) {
                int op; scanf("%d", &op);
                if(op == 1) {
                    int x; scanf("%d", &x);
                    printf("%lld
    ", query(x));
                }
                else if(op == 2) {
                    int x, y;
                    scanf("%d%d", &x, &y);
                    modifyEdge(pa[x], x, y - w[x]);
                    w[x] = y;
                }
                else {
                    int x, y;
                    scanf("%d%d", &x, &y);
                    modifyPoint(x, y);
                }
            }
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    Java数据结构学习Day2_Java基础排序算法
    Java数据结构学习Day1_队列_用数组模拟队列以及环形队列
    Java数据结构学习Day1_稀疏数组
    系统结构实践第七次作业——23组
    第04组 Alpha事后诸葛亮
    第04组 Alpha冲刺(4/4)
    第04组 Alpha冲刺(3/4)
    第04组 Alpha冲刺(2/4)
    第04组 Alpha冲刺(1/4)
    第四组团队git现场编程实战
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11542522.html
Copyright © 2011-2022 走看看