zoukankan      html  css  js  c++  java
  • 技能树

    题目描述

    “OI 的学习,理应循序渐进”。

    OI 中技能的加点形如一棵以 $1$ 为根的树形结构,每个点的父亲就是它的前置知识,比如“min25 筛”应该在“莫比乌斯反演”之后学习,“主席树”应该在“树状数组”之后学习,形式化的来说,对于树上每个节点 $u$ ,必须先学前置知识,也就是它在技能树上父亲 $fa(u)$ 。

    学习知识的过程可能是痛苦的,也可能是愉悦的,学习 $i$ 号知识需要消耗 $a_i$ 点愉悦度,学完之后因为满满的成就感会增加 $b_i$ 点愉悦度,注意,此处先结算 $a_i$ 后结算 $b_i$ ,二者并非同一时刻结算。

    现在,我们已经学习完了 $1$ 号知识点,并拥有了一个未知的初始愉悦度,因为我们不希望学习过程中出现过分痛苦的情况,所以我们想知道:至少需要多少点初始愉悦度,使得能通过合理的学习顺序学习完技能树上所有知识,并且学习过程中任意时刻愉悦度都不为负?

    数据范围

    $n le 10^5,0 le a_i,b_i le 10^9$

    题解

    可以先考虑序列上如何操作。

    首先我们应该选择那些 $a_i le b_i$ 的点,对于这些点我们应先选择 $a_i$ 更小的。

    对于那些 $a_i > b_i$ 的点,可以假定 $i$ 比 $j$ 更优,然后列出不等式,发现满足这个的条件是 $b_i>b_j$ ,所以从 $b_i$ 大的开始选即可。

    考虑在一棵树上,因为有父亲的限制,所以不能像上述贪心,我们发现如果有一个优先级最高的点,如果它的父亲被选了,那下一个一定会选它,所以维护优先队列,每次选择优先级最高的,跟当前父亲合并即可,这个可以用并查集实现。

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    const int N=2e5+5; LL a[N],b[N];
    int n,fa[N],f[N],hd[N],V[N],nx[N],t;
    struct O{
        int x;
        friend bool operator < (const O& A,const O& B){
            if (b[A.x]>=a[A.x] && b[B.x]>=a[B.x])
                return a[A.x]>a[B.x];
            if (b[A.x]<a[A.x] && b[B.x]<a[B.x])
                return b[A.x]<b[B.x];
            return b[A.x]<a[A.x];
        }
    };
    priority_queue<O>q;
    int get(int x){
        return f[x]==x?x:f[x]=get(f[x]);
    }
    void add(int u,int v){
        nx[++t]=hd[u];V[hd[u]=t]=v;
    }
    void dfs(int x,int fr){
        fa[f[x]=x]=fr;
        for (int i=hd[x];i;i=nx[i])
            if (V[i]!=fr) dfs(V[i],x);
    }
    int main(){
        cin>>n;
        for (int i=2;i<=n;i++)
            scanf("%lld%lld",&a[i],&b[i]),
            q.push((O){i});
        for (int x,y,i=1;i<n;i++)
            scanf("%d%d",&x,&y),
            add(x,y),add(y,x);
        dfs(1,0);int u,v;LL A,B;
        while(!q.empty()){
            u=q.top().x;q.pop();
            v=get(fa[u]);f[u]=v;
            A=max(a[v],a[v]-b[v]+a[u]);
            B=b[v]+b[u]-a[v]-a[u]+A;
            a[v]=A;b[v]=B;
        }
        printf("%lld
    ",a[1]);return 0;
    }
  • 相关阅读:
    20145229吴姗珊《信息安全系统设计基础》第3周学习总结
    20145229《信息安全系统设计基础》第2周学习总结
    20145207 myeclipse测试
    20145207 ms11_050漏洞攻击
    20145207 ms08_067攻击实验
    20145207《Java程序设计》实验一(Java开发环境的熟悉)实验报告
    20145207《Java程序设计》第7周学习总结
    20145207李祉昂《网络对抗技术》恶意代码分析
    20145207《Java程序设计》第6周学习总结
    20145207《网络对抗》免杀原理与实践
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11808144.html
Copyright © 2011-2022 走看看