zoukankan      html  css  js  c++  java
  • hdu6133 Army Formations 线段树合并

    给你一棵有n个节点的二叉树,每个节点有一个权值,对于一棵子树u,将u的子树中的节点权值从大到小排序,令sz[u]为子树u的大小,

    则ans[u] = 1 * a[1] + 2 * a[2] + ... + sz[u] * a[sz[u]],其中a[1] >= a[2] >= ... >= a[u]。求所有节点的答案。

    对每个节点建立权值线段树,dfs整棵树,线段树合并

    ans[rt] = ans[ls[rt]] + ans[rs[rt]] + size[ls[rt]] * w[rs[rt]],w表示某权值区间的权值和,size表示某权值区间内点的个数。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int maxn = 1e5 + 10;
    const int maxnode = 2e6 + 10;
    struct edge { int to, next; }e[maxn << 1];
    int head[maxn], ecnt;
    void edge_init() { ecnt = 0; memset(head, -1, sizeof(head)); }
    void add(int u, int v) {
        e[ecnt].to = v; e[ecnt].next = head[u]; head[u] = ecnt++;
    }
    int a[maxn], b[maxn];
    int root[maxn];
    int sz[maxnode], ls[maxnode], rs[maxnode];
    long long ans[maxnode], sum[maxnode];
    int tot, m;
    
    int mergeleaf(int u, int v) {
        sz[u] += sz[v];
        sum[u] += sum[v];
        ans[u] = sum[u] / (long long)sz[u] * (long long) sz[u] * (long long) (sz[u] + 1LL) / 2LL;
        return u;
    }
    
    int merge(int u, int v, int l, int r) {
        if (!u || !v) return u | v;
        if (l == r) return mergeleaf(u, v);
        int mid = (l + r) >> 1;
        ls[u] = merge(ls[u], ls[v], l, mid);
        rs[u] = merge(rs[u], rs[v], mid + 1, r);
        sz[u] = sz[ls[u]] + sz[rs[u]];
        sum[u] = sum[ls[u]] + sum[rs[u]];
        ans[u] = ans[ls[u]] + ans[rs[u]] + sum[ls[u]] * (long long) sz[rs[u]];
        return u;
    }
    
    void update(int x, int &rt, int l, int r) {
        if (!rt) rt = ++tot;
        sum[rt] = ans[rt] = (long long) b[x];
        sz[rt] = 1;
        if (l == r) return;
        int mid = (l + r) >> 1;
        if (x <= mid) update(x, ls[rt], l, mid);
        else update(x, rs[rt], mid + 1, r);
    }
    
    void dfs(int u, int fa) {
        update(a[u], root[u], 1, m);
        for (int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].to;
            if (v == fa) continue;
            dfs(v, u);
            root[u] = merge(root[u], root[v], 1, m);
        }
    }
    
    int main() {
        int T, n;
        scanf("%d", &T);
        while (T--) {
            edge_init();
            scanf("%d", &n);
            for (int i = 1; i <= n; ++i) scanf("%d", a + i), b[i] = a[i];
            sort(b + 1, b + 1 + n);
            m = unique(b + 1, b + 1 + n) - (b + 1);
            for (int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + 1 + m, a[i]) - b;
            for (int u, v ,i = 1; i < n; ++i) {
                scanf("%d%d", &u, &v);
                add(u, v); add(v, u);
            }
            tot = 0;
            memset(root, 0, sizeof(root));
            dfs(1, 0);
            for (int i = 1; i <= n; ++i) printf("%lld ", ans[root[i]]);
            puts("");
            for (int i = 1; i <= tot; ++i) ls[i] = rs[i] = sum[i] = ans[i] = sz[i] = 0;
        }
    }
     
  • 相关阅读:
    hdu6229 Wandering Robots 2017沈阳区域赛M题 思维加map
    hdu6223 Infinite Fraction Path 2017沈阳区域赛G题 bfs加剪枝(好题)
    hdu6438 Buy and Resell 买卖物品 ccpc网络赛 贪心
    hdu6441 Find Integer 求勾股数 费马大定理
    bzoj 1176 Mokia
    luogu 3415 祭坛
    bzoj 1010 玩具装箱
    bzoj 3312 No Change
    luogu 3383【模板】线性筛素数
    bzoj 1067 降雨量
  • 原文地址:https://www.cnblogs.com/tempestT/p/7666282.html
Copyright © 2011-2022 走看看