zoukankan      html  css  js  c++  java
  • BZOJ2809 dispatching

    题目大意

      给你一棵有根树,每个节点内有两个值:领导力和费用。现要求选择一个子树,并在子树内选择若干个节点,使得选择的节点的费用总和不超出预算,且子树的根的领导力乘以选择的节点的数量的值最大。

    思路

      由贪心思想,处理每个子树时,我们优先保留费用低的节点,当节点的总费用超出预算时,我们优先去除费用最高的节点。贪心的优越正确性显然。要达到这一点,我们很容易想到用大根堆来维护。问题在于,怎么生成这个堆呢?可以看到一个子树的堆可以由它的各个子树的堆合并而成。所以我们的堆用可并堆。按照Dfs后序遍历处理各个子树即可。

    注意事项

    • 堆合并后,要更新堆的根。
    • 注意运算时要开long long。
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    const int MAX_NODE = 100010;
    
    template<class KeyType>
    
    struct Heap
    {
    private:
        struct Node
        {
            Node *Father, *LeftSon, *RightSon;
            int Dist, Size;
            KeyType Key, Sum;
            
            Node(int key) : Father(NULL), LeftSon(NULL), RightSon(NULL), Key(key), Sum(key), Dist(0), Size(1) {}
            
            void Refresh()
            {
                Dist = RightSon ? RightSon->Dist + 1 : 0;
                Sum = Key;
                Size = 1;
                if (LeftSon)
                {
                    Sum = Sum + LeftSon->Sum;
                    Size += LeftSon->Size;
                }
                if (RightSon)
                {
                    Sum = Sum + RightSon->Sum;
                    Size += RightSon->Size;
                }
            }
        }*Root;
        
        Node *Merge(Node *a, Node *b)
        {
            if(!a)
                return b;
            if (!b)
                return a;
            if(a->Key < b->Key)
                swap(a, b);
            a->RightSon = Merge(a->RightSon, b);
            if(a->RightSon)
                a->RightSon->Father = a;
            if((a->LeftSon ? a->LeftSon->Dist : 0) < (a->RightSon ? a->RightSon->Dist : 0))
                swap(a->LeftSon, a->RightSon);
            a->Refresh();
            return a;
        }
        
    public:
        Heap() :Root(NULL){}
        
        void Intake(Heap *a)
        {
            Root = Merge(Root, a->Root);
        }
        
        void Push(KeyType key)
        {
            Root = Merge(Root, new Node(key));
        }
        
        void Pop()
        {
            Root = Merge(Root->LeftSon, Root->RightSon);
        }
        
        KeyType Sum()
        {
            if(!Root)
                return 0;
            return Root->Sum;
        }
        
        int Size()
        {
            if (!Root)
                return 0;
            return Root->Size;
        }
    };
    
    struct Graph
    {
    private:
        int M;
        long long Ans;
        
        struct Node
        {
            vector<Node*> Sons;
            int Cost, Val;
            
            Node(){}
            
            Node(int cost, int val) : Cost(cost), Val(val) {}
        }_nodes[MAX_NODE], *Root;
        int _vCount;
        
        Heap<long long> *Dfs(Node *cur)
        {
            Heap<long long> *curHeap = new Heap<long long>();
            if (cur == NULL)
                return curHeap;
            for (int i = 0; i < cur->Sons.size(); i++)
                curHeap->Intake(Dfs(cur->Sons[i]));
            curHeap->Push(cur->Cost);
            while (curHeap->Sum() > M)
                curHeap->Pop();
            Ans = max(Ans, (long long)cur->Val * (long long)curHeap->Size());
            return curHeap;
        }
        
    public:
        void Init(int n, int m)
        {
            _vCount = n;
            M = m;
            Ans = 0;
        }
        
        void SetNode(int cur, int fa, int cost, int val)
        {
            if(fa != 0)
                _nodes[fa].Sons.push_back(_nodes + cur);
            else
                Root = _nodes + cur;
            _nodes[cur].Cost = cost;
            _nodes[cur].Val = val;
        }
        
        long long GetAns()
        {
            Dfs(Root);
            return Ans;
        }
    }g;
    
    int main()
    {
        int totNode, m, fa, cost, val;
        scanf("%d%d", &totNode, &m);
        g.Init(totNode, m);
        for (int i = 1; i <= totNode; i++)
        {
            scanf("%d%d%d", &fa, &cost, &val);
            g.SetNode(i, fa, cost, val);
        }
        printf("%lld
    ", g.GetAns());
        return 0;
    }
    View Code
  • 相关阅读:
    tcp_tw_recycle 的问题, 使用某一个wifi,APP老是连接不上网络
    stackoverflow 的架构
    服务器的返回码总结
    iOS10 app连接不上网络的问题
    nsurl 测试ATS
    处理数据队列
    换手率的公司使用MQTT的框架
    导入charts开源库到工程里面
    极光推送的推送方式
    自己生成一个NDK的浅析
  • 原文地址:https://www.cnblogs.com/headboy2002/p/9360686.html
Copyright © 2011-2022 走看看