https://www.lydsy.com/JudgeOnline/problem.php?id=2809
先求树图的dfs序 对dfs序列从前到后建立静态主席树 维护对应工资区间上有多少人
枚举每个点 找到以该点为根的子树对应的区间 前缀和做差得到一棵线段树 区间二分查询 先看左子树工资上够不够 够就把人都算上再查右树 不够就从左树再递归
还有要注意的是 离散化后不能去重 因为需要求人数 如果离散化后再建树 会把很多人算在同一工资水平 这样边界处理会很恶心
#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct node0
{
int id;
ll val;
};
struct node1
{
int v;
int next;
};
struct node2
{
int l;
int r;
ll val;
int cnt;
};
node0 tmp[100010];
node1 edge[100010];
node2 tree[2000010];
ll cval[100010],lval[100010];
int first[100010],pos[100010],root[100010],fa[100010],mp1[100010],mp2[100010],sum[100010];
ll tot;
int n,num;
bool cmp(node0 n1,node0 n2)
{
return n1.val<n2.val;
}
ll getmax(ll a,ll b)
{
if(a>b) return a;
else return b;
}
void addedge(int u,int v)
{
edge[num].v=v;
edge[num].next=first[u];
first[u]=num++;
}
void dfs(int cur)
{
int i,v;
num++;
mp1[cur]=num,mp2[num]=cur,sum[cur]=1;
for(i=first[cur];i!=-1;i=edge[i].next)
{
v=edge[i].v;
dfs(v);
sum[cur]+=sum[v];
}
}
int build(int l,int r)
{
int cur,m;
cur=num++;
tree[cur].l=0,tree[cur].r=0,tree[cur].val=0,tree[cur].cnt=0;
if(l==r) return cur;
m=(l+r)/2;
tree[cur].l=build(l,m);
tree[cur].r=build(m+1,r);
return cur;
}
int update(int rot,int tar,ll val,int l,int r)
{
int cur,m;
cur=num++;
tree[cur]=tree[rot];
tree[cur].val+=val;
tree[cur].cnt++;
if(l==r) return cur;
m=(l+r)/2;
if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m);
else tree[cur].r=update(tree[rot].r,tar,val,m+1,r);
return cur;
}
void init()
{
int i;
num=0;
root[0]=build(1,n);
for(i=1;i<=n;i++)
{
root[i]=update(root[i-1],pos[mp2[i]],cval[mp2[i]],1,n);
}
}
int query(int lrot,int rrot,ll val,int l,int r)
{
ll res;
int m;
if(l==r)
{
if(val>=tree[rrot].val-tree[lrot].val) return tree[rrot].cnt-tree[lrot].cnt;
else return 0;
}
res=tree[tree[rrot].l].val-tree[tree[lrot].l].val,m=(l+r)/2;
if(val<=res) return query(tree[lrot].l,tree[rrot].l,val,l,m);
else return tree[tree[rrot].l].cnt-tree[tree[lrot].l].cnt+query(tree[lrot].r,tree[rrot].r,val-res,m+1,r);
}
ll solve()
{
ll res,cnt;
int i,pl,pr,p;
res=0;
for(i=1;i<=n;i++)
{
pl=mp1[i],pr=mp1[i]+sum[i]-1;
cnt=query(root[pl-1],root[pr],tot,1,n);
res=getmax(res,cnt*lval[i]);
}
return res;
}
int main()
{
int i;
while(scanf("%d%lld",&n,&tot)!=EOF)
{
memset(first,-1,sizeof(first));
num=0;
for(i=1;i<=n;i++)
{
scanf("%d%lld%lld",&fa[i],&cval[i],&lval[i]);
tmp[i].id=i,tmp[i].val=cval[i];
if(i>1) addedge(fa[i],i);
}
sort(tmp+1,tmp+n+1,cmp);
for(i=1;i<=n;i++) pos[tmp[i].id]=i;
num=0;
dfs(1);
init();
printf("%lld\n",solve());
}
return 0;
}