zoukankan      html  css  js  c++  java
  • HDU

    HDU - 5788

    我们考虑把每个点遍历一遍, 把枚举的当前的这个点改成100000对答案的影响。

    如果我们把 u 变成 100000, 受到影响的是 u 以及它的祖先,

    我们记midu为子树u的中位数, nexmidu为子树u中位数的下一个数。

    只有 a[ u ]的值小于等于祖先的mid, 才会改变祖先的薪水, 变成nexmidu。

    所以我们用主席树求出每个子树的mid 和 nexmid。 然后dfs一遍整棵树, 用树状数组去更新答案。

    #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 = 1e5 + 7;
    const int inf = 0x3f3f3f3f;
    const LL INF = 0x3f3f3f3f3f3f3f3f;
    const int mod = 998244353;
    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;}
    
    int n, a[N];
    int needVal[N];
    int addVal[N];
    
    vector<int> G[N];
    int in[N], ot[N], sz[N], idx;
    
    LL ans, allVal;
    
    struct ChairManTree {
        int Rt[N], treecnt;
        void init() {
            treecnt = 0;
        }
        struct Node {
            int sum, ls, rs;
        } a[N * 20];
        void update(int p, int val, int l, int r, int &x, int y) {
            x = ++treecnt;
            a[x] = a[y];
            a[x].sum += val;
            if(l == r) return;
            int mid = l + r >> 1;
            if(p <= mid) update(p, val, l, mid, a[x].ls, a[y].ls);
            else update(p, val, mid + 1, r, a[x].rs, a[y].rs);
        }
        int query(int k, int l, int r, int x, int y) {
            if(l == r) return l;
            int mid = l + r >> 1;
            if(a[a[x].ls].sum - a[a[y].ls].sum >= k) return query(k, l, mid, a[x].ls, a[y].ls);
            else return query(k - a[a[x].ls].sum + a[a[y].ls].sum, mid + 1, r, a[x].rs, a[y].rs);
        }
    } C;
    
    struct Bit {
        LL a[N];
        void init() {
            for(int i = 1; i < N; i++) {
                a[i] = 0;
            }
        }
        inline void update(int x, int v) {
            for(int i = x; i < N; i += i & -i) {
                a[i] += v;
            }
        }
        inline LL sum(int x) {
            LL ans = 0;
            for(int i = x; i; i -= i & -i) {
                ans += a[i];
            }
            return ans;
        }
    } Tree;
    
    int dfs(int u) {
        in[u] = ++idx;
        C.update(a[u], 1, 1, 100000, C.Rt[idx], C.Rt[idx - 1]);
        sz[u] = 1;
        for(auto &v : G[u]) {
            dfs(v);
            sz[u] += sz[v];
        }
        ot[u] = idx;
    }
    
    void solve(int u) {
        Tree.update(100001 - needVal[u], addVal[u]);
        chkmax(ans, Tree.sum(100000 - a[u] + 1));
        for(auto &v : G[u]) {
            solve(v);
        }
        Tree.update(100001 - needVal[u], -addVal[u]);
    }
    
    void init() {
        ans = allVal = idx = 0;
        C.init(); Tree.init();
        for(int i = 1; i <= n; i++) {
            G[i].clear();
        }
    }
    int main() {
        while(scanf("%d", &n) != EOF) {
            init();
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
            }
            for(int i = 2; i <= n; i++) {
                int p; scanf("%d", &p);
                G[p].push_back(i);
            }
            dfs(1);
            for(int i = 1; i <= n; i++) {
                if(sz[i] == 1) {
                    needVal[i] = a[i];
                    addVal[i] = 100000 - a[i];
                    allVal += a[i];
                }
                else {
                    int mid = sz[i] + 1 >> 1;
                    needVal[i] = C.query(mid, 1, 100000, C.Rt[ot[i]], C.Rt[in[i] - 1]);
                    addVal[i] = C.query(mid + 1, 1, 100000, C.Rt[ot[i]], C.Rt[in[i] - 1]) - needVal[i];
                    allVal += needVal[i];
                }
            }
            solve(1);
            printf("%lld
    ", ans + allVal);
        }
        return 0;
    }
    
    /*
    */
  • 相关阅读:
    Android实例-Delphi在运行时更改Android屏幕旋转(IOS也支持,不过我可没有苹果机,测试不了)
    delphi实现电脑屏幕旋转(电脑屏幕,不是手机屏幕)
    教程-关于escape和URI之间的不同!
    在Delphi中URLEncode文件名的最佳方法是什么?
    Delphi实现js中的escape()编码和unescape()解码
    面向对象: 接口与对象生存周期,接口自动释放
    问题-Delphi在做窗体派生时提示Resource TForm2 not found
    问题-delphi idTCPserver-Socket error问题详解
    delphi 求两个时间差
    Delphi 解决StrToDateTime()不是有效日期类型的问题
  • 原文地址:https://www.cnblogs.com/CJLHY/p/11492767.html
Copyright © 2011-2022 走看看