p1552 [APIO2012]派遣

Posted 水题收割者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了p1552 [APIO2012]派遣相关的知识,希望对你有一定的参考价值。

传送门

分析

首先这个题有两个坑点

一是一个点不管可以由父亲领导,任何祖宗均可领导

而是根节点的花费要算在总费用中且它自己也算在总节点数量中

于是我们考虑如何求答案

首先我们知道对于一个点如果在一个子树中就没有选则在更大的一棵子树中一定不会选

因为一棵大的子树有更多选择,结果肯定不会比它的子树劣

于是我们可以每个节点开一个优先队列,每次将超过范围的点直接删掉

于是合并两棵子树是暴力启发式合并即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define int long long
vector<int>v[100100];
int c[100100],l[100100],now[100100],d[100100],sum[100100],n,m,Ans;
priority_queue<int>q[100100];
inline void mer(int u,int x,int y){
    if(q[x].size()<q[y].size()){
      swap(x,y);
      now[u]=x;
    }
    while(!q[y].empty()){
      q[x].push(q[y].top());
      q[y].pop();
    }
}
inline void del(int x){
    while(sum[x]>m){
      sum[x]-=q[now[x]].top();
      q[now[x]].pop();
    }
}
inline void work(int x){
    now[x]=x;
    q[now[x]].push(c[x]);
    sum[x]+=c[x];
    for(int i=0;i<v[x].size();i++){
      work(v[x][i]);
      sum[x]+=sum[v[x][i]];
      mer(x,now[x],now[v[x][i]]);
    }
    del(x);
    int y=q[now[x]].size();
    if(y*l[x]>Ans)Ans=y*l[x];
}
signed main(){
    int i,j,k;
    scanf("%lld%lld",&n,&m);
    for(i=1;i<=n;i++){
      scanf("%lld%lld%lld",&k,&c[i],&l[i]);
      if(k){
        v[k].push_back(i);
        d[i]++;
      }
    }
    for(i=1;i<=n;i++)
      if(!d[i])work(i);
    cout<<Ans;
    return 0;
}

以上是关于p1552 [APIO2012]派遣的主要内容,如果未能解决你的问题,请参考以下文章

[luogu P1552] [APIO2012]派遣

P1552 [APIO2012]派遣

P1552 [APIO2012]派遣

Luogu P1552 [APIO2012]派遣 主席树

[洛谷P1552] [APIO2012]派遣(左偏树)

[APIO2012]派遣