• codeforce 600E


    codeforces 600E E. Lomsat gelral

    传送门:https://codeforces.com/contest/600/problem/E

    题意:

    给你一颗n个节点的树,树上的每一个节点都有一种颜色,询问每一个节点所在的子树颜色数量最多的那些颜色的值的总和

    题解:

    考虑暴力做法,用一个数组能表示出所有状态。然后合并状态进行考虑,那么对于每个节点开一个这样的数组,明显空间不够。那么就动态开点,那么对于合并,数组合并o(n),考虑线段树合并。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 1e5 + 10;
    const int M = 2e5 + 10;
    
    int n;
    int h[N], e[M], ne[M], idx;
    
    struct node
    {
        ll dat, cnt;
        int l, r;
    }tr[N * 30];
    
    int root[N], tot;
    ll w[N], ans[N];
    
    void add(int a, int b)
    {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx ++;
    }
    
    void update(int p)
    {
        if(tr[tr[p].l].cnt > tr[tr[p].r].cnt)
        {
            tr[p].cnt = tr[tr[p].l].cnt;
            tr[p].dat = tr[tr[p].l].dat;
            return ;
        }
        else if(tr[tr[p].l].cnt < tr[tr[p].r].cnt)
        {
            tr[p].cnt = tr[tr[p].r].cnt;
            tr[p].dat = tr[tr[p].r].dat;
            return ;
        }
        else
        {
            tr[p].cnt = tr[tr[p].l].cnt;
            tr[p].dat = tr[tr[p].l].dat + tr[tr[p].r].dat;
            return ;
        }
    }
    
    void insert(int &p, int l, int r, int c)
    {
        if(!p) p = ++ tot;
        if(l == r)
        {
            tr[p].cnt ++;
            tr[p].dat = c;
            return ;
        }
        int mid = l + r >> 1;
        if(c <= mid) insert(tr[p].l, l, mid, c);
        else insert(tr[p].r, mid + 1, r, c);
        update(p);
    }
    
    int merge(int p, int q, int l, int r)
    {
        if(!p) return q;
        if(!q) return p;
        if(l == r)
        {
            tr[p].cnt += tr[q].cnt;
            return p;
        }
        int mid = l + r >> 1;
        tr[p].l = merge(tr[p].l, tr[q].l, l, mid);
        tr[p].r = merge(tr[p].r, tr[q].r, mid + 1, r);
        update(p);
        return p;
    }
    
    void dfs(int x, int fa)
    {
        insert(root[x], 1, n, w[x]);
        for (int i = h[x]; ~i; i = ne[i])
        {
            int j = e[i];
            if(j == fa) continue;
            dfs(j, x);
            root[x] = merge(root[x], root[j], 1, n);
        }
        ans[x] = tr[root[x]].dat;
    }
    
    int main()
    {
        memset(h, -1, sizeof(h));
        scanf("%d", &n);
        for (int i = 1; i <= n; i ++)
            scanf("%lld", &w[i]);
        for (int i = 0; i < n - 1; i ++)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            add(a, b), add(b, a);
        }
        dfs(1, -1);
        for (int i = 1; i <= n; i ++)
        {
            printf("%lld%c", ans[i], i == n? '
    ' : ' ');
        }
    }
  • 相关阅读:
    第二阶段冲刺第五天(6月4号)
    第二阶段冲刺第四天(6月3号)
    第二次阶段冲刺第三天(6月2号)
    第二次阶段冲刺第二天(6月1号)
    第二次阶段冲刺第一天(5月31号)
    第十周学习进度
    第十一周学习进度
    第十二周学习进度
    javascript 将递归转化为循环
    创建数据库,并设置外部访问权限
  • 原文地址:https://www.cnblogs.com/xwdzuishuai/p/12061803.html
Copyright © 2020-2023  润新知