BZOJ-2809-dispatching(枚举+dfs序建主席树)
作者:互联网
题目
题意:已知条件:人数,上线薪水m,每一个人都有一个上级,薪水,领导能力。
找出一个人,从他所掌管的所有员工里随意选出几个员工,但这些员工的总薪水要<=m,求这个人的领导能力*员工个数的最大值。
思路:枚举+dfs序建主席树
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int N=1e5+5,M=N;
int ea[N],ab[N],refl[N],cnt;
int in[N],out[N],fp[N],ovo;
int head[N],tot;
struct tree{int l,r,num;}t[N*50];
int root[N],sz;ll sum[N*50];
struct Edge{int to,nex;}edge[N];
void add(int from,int to)
{
edge[++tot]=(Edge){to,head[from]};head[from]=tot;
}
void dfs(int x)
{
in[x]=ovo++,fp[ovo-1]=x;
for(int i=head[x];i;i=edge[i].nex)
dfs(edge[i].to);
out[x]=ovo-1;
}
void build(int wh,int val,int &x,int y,int l,int r)
{
x=++sz,t[x]=t[y],t[x].num++,sum[x]=sum[y]+val;
if(l==r)
return;
int mid=(l+r)>>1;
if(wh<=mid)
build(wh,val,t[x].l,t[y].l,l,mid);
else
build(wh,val,t[x].r,t[y].r,mid+1,r);
}
int query(int x,int y,int k,int l,int r)//一定要注意是右子树-左子树!!!!一定不能马虎T_T
{
if(l==r)
{
ll summ=sum[y]-sum[x];int numm=t[y].num-t[x].num;
if(summ<=k)
return numm;
else //这些numm个不可以完全返回,只能返回的个数总sum要<=k;
return k/(summ/numm);
}
ll left=sum[t[y].l]-sum[t[x].l];
int mid=(l+r)>>1;
if(left<=k)//权值线段树中的左子树的总sum(薪水)<=k,询问右子树薪水不超过k-left的最大num+左子树的所有num(员工个数)
return t[t[y].l].num-t[t[x].l].num+query(t[x].r,t[y].r,k-left,mid+1,r);
else
return query(t[x].l,t[y].l,k,l,mid);
}
int main()
{
// m(head,0),tot=0,ovo=1;
int n,m,master=1;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int fa;scanf("%d%d%d",&fa,&ea[i],&ab[i]);
add(fa,i);//因为每个节点的fa编号小于自己 所以master=1,建立单向边即可,dfs序也不需(vis标记是否为已访问过的其父/或者用fa[]判断)
refl[i]=ea[i];
}
sort(refl+1,refl+n+1);
cnt=unique(refl+1,refl+n+1)-(refl+1);
ovo=1;
dfs(master);--ovo;//(ovo==n)
for(int i=1;i<=ovo;i++)//根据dfs之后新序列建树。
{
int x=fp[i],dex=lower_bound(refl+1,refl+cnt+1,ea[x])-refl;//x是指dfs序中第i个对应原序列的第几个
build(dex,ea[x],root[i],root[i-1],1,cnt);
}
ll maxn=0;
for(int i=1;i<=n;i++)
{
ll ans=(ll)ab[i]*query(root[in[i]-1],root[out[i]],m,1,cnt);//根据[in[i],out[i]] dfs序查询。注意(ll)。
maxn=max(maxn,ans);
}
printf("%lld\n",maxn);
}
标签:head,int,dfs,edge,dispatching,2809,include,ovo 来源: https://blog.csdn.net/qq_42576687/article/details/90137071