这题还是非常显然的
题意大概是随便选一个点x,树上每点有点权(v[x])和一个代价(c[x]),你有一个值m,设,我们用m可以最多大于y[x]个x的子树中代价的和,求出所有点的y[x]*v[x]的值,其中最大值就是答案。
非常显然用线段树合并
还有可并堆的做法,不怎么会会,下次学
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<fstream>
using namespace std;
int lch[5000010],rch[5000010];
long long sum[5000010];
int cnt[5000010];
int idx;
int root[200010];
int merge(int u,int v){
if(!u) return v;
if(!v) return u;
int t=++idx;
sum[t]=sum[u]+sum[v];
cnt[t]=cnt[u]+cnt[v];
lch[t]=merge(lch[u],lch[v]);
rch[t]=merge(rch[u],rch[v]);
return t;
}
void ins(int &rt,int l,int r,int x,int val){
if(!rt){
rt=++idx;
}
sum[rt]+=val,cnt[rt]++;
if(l==r){
return;
}
int mid=(l+r)/2;
if(x<=mid){
ins(lch[rt],l,mid,x,val);
}else{
ins(rch[rt],mid+1,r,x,val);
}
}
int bisearch(int rt,int l,int r,int limit){
if(!rt){
return 0;
}
if(l==r){
if(sum[rt]<=limit){
return 1;
}else{
return 0;
}
}
int mid=(l+r)/2;
if(limit>sum[lch[rt]]){
return cnt[lch[rt]]+bisearch(rch[rt],mid+1,r,limit-sum[lch[rt]]);
}else{
return bisearch(lch[rt],l,mid,limit);
}
}
struct node{
int a,b;
inline bool operator<(const node &v)const{
return a<v.a;
}
};
int n,m;
int b[100010],c[100010];
long long l[100010];
node t[100010];
int rk[100010];
long long ans;
int main(){
int i,j,k;
cin>>n>>m;
for(i=1;i<=n;++i){
cin>>b[i]>>c[i]>>l[i];
t[i]={c[i],i};
}
stable_sort(t+1,t+n+1);
for(i=1;i<=n;++i){
k=t[i].b;
rk[k]=i;
root[k]=++idx;
ins(root[k],1,n+1,rk[k],c[k]);
}
for(i=n;i;--i){
ans=max(ans,l[i]*bisearch(root[i],1,n+1,m));
if(b[i]){
root[b[i]]=merge(root[b[i]],root[i]);
}
}
cout<<ans<<endl;
return 0;
}