AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2809
【题解】
对于题上给的树,我们在它的dfs序上瞎搞。
我们按照dfs序建主席树,主席树中以花费的离散值为权,并维护总花费。
然后查询答案的时候,枚举每个点为管理者的情况,计算答案。
这样问题就转化为了在子树内找到最多的点,使得这些点的花费小于m,用主席树就能完美解决这个问题。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
#define FILE "read"
#define MAXN 100010
#define up(i,j,n) for(ll i=j;i<=n;++i)
#define dn(i,j,n) for(ll i=j;i>=n;--i)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline ll read(){
ll x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
struct node{ll y,next;}e[MAXN*2];
ll n,m,len,dfs_clock,tot,cnt,ans,Link[MAXN],a[MAXN],b[MAXN],num[MAXN],hash[MAXN],root[MAXN],dfn[MAXN],size[MAXN];
ll sum[MAXN<<5],cost[MAXN<<5],son[MAXN<<5][2];
void insert(ll x,ll y){e[++len].next=Link[x];Link[x]=len;e[len].y=y;}
void dfs(ll x,ll fa){
dfn[++dfs_clock]=x; size[x]=1;
for(ll i=Link[x];i;i=e[i].next)
if(e[i].y!=fa) dfs(e[i].y,x),size[x]+=size[e[i].y];
}
ll find(ll x){
ll l=1,r=tot;
while(l+1<r){
ll mid=(l+r)>>1;
if(hash[mid]<=x) l=mid;
else r=mid;
}
return hash[l]==x?l:r;
}
ll newroot(ll last,ll v){
sum[++cnt]=sum[last]+1; cost[cnt]=cost[last]+v;
son[cnt][0]=son[last][0]; son[cnt][1]=son[last][1];
return cnt;
}
void updata(ll l,ll r,ll &root,ll last,ll x){
root=newroot(last,hash[x]);
if(l==r) return;
ll mid=(l+r)>>1;
if(x<=mid) updata(l,mid,son[root][0],son[last][0],x);
else updata(mid+1,r,son[root][1],son[last][1],x);
}
ll ask(ll l,ll r,ll root,ll last,ll lim){
if(l==r) return min(lim/hash[l],sum[root]-sum[last]);
ll mid=(l+r)>>1,temp=cost[son[root][0]]-cost[son[last][0]];
if(temp>lim) return ask(l,mid,son[root][0],son[last][0],lim);
else return sum[son[root][0]]-sum[son[last][0]]+ask(mid+1,r,son[root][1],son[last][1],lim-temp);
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
n=read(); m=read();
up(i,1,n){
ll x=read(); a[i]=num[i]=read(); b[i]=read();
if(x) insert(i,x),insert(x,i);
}
dfs(1,0); sort(num+1,num+n+1); hash[++tot]=num[1];
up(i,2,n) if(num[i]!=num[i-1]) hash[++tot]=num[i];
up(i,1,n) updata(1,tot,root[i],root[i-1],find(a[dfn[i]]));
up(i,1,n) cmax(ans,b[dfn[i]]*ask(1,tot,root[i+size[dfn[i]]-1],root[i-1],m));
printf("%lld\n",ans);
return 0;
}