在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者 i的上级 Bi,薪水Ci,领导力L i,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。
 
$1≤N≤100000$ 忍者的个数;
$1≤M≤1000000000$ 薪水总预算; 
$0≤B_i < i$ 忍者的上级的编号;
$1≤C_i≤M$   忍者的薪水;
$1≤L_i≤1000000000$   忍者的领导力水平。
 
题解:
  问题等价于,每一个点最多能在子树上取多少点,花费小于M?
  显然的是,我们的策略一定是从最小的点开始取,直到超过$M$为止,这显然是贪心的过程
  然后得枚举所有点,总复杂度$O(n^2)$
  然后考虑优化,
  我们把问题"询问一个点,其子树上之和大于$M$的$x$个权值最小的点"
  转化成"询问一个区间,查询一个区间上和小于等于$M$的$x$个最小的元素"
  显然,后者是主席树可以解决的,单次操作的复杂度就从$O(n)$变成了$O(log(n))$
  然后我们用$dfs$序将树拍扁,变成序列即可解决问题,就完成了优化
  具体过程就是
  $dfs(master)$得到$dfs$序,离散化花费
  主席树保存两个值,一个是点数,一个是花费,单点更新,区间求和
  按照$dfs$序列插入权值,构造n颗树
  最后,遍历每个点,每个点等价于一个区间询问,枚举所有点就能得到最大值
  (这道题网上的主席树题解代码真是乱写,反正我是没懂他们是怎么写的,AC是AC了,莫名其妙多此一举的操作一大堆)
#include <bits/stdc++.h>
#define nd seg[now]
#define ndp seg[pre]
#define mid ((s+t)>>1)
#define ll long long
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
int casn,n,k;
ll m;
struct node2{
int to,next;
}e[maxn];
int head[maxn],nume;
int tin[maxn],tout[maxn];
ll cost[maxn],pos[maxn],power[maxn];
int rt[maxn],size,cnt,pre[maxn],dfn[maxn];
int cmp(int a,int b){
return cost[a]<cost[b];
}
inline void add(int a,int b){
e[++nume]=(node2){b,head[a]};
head[a]=nume;
}
void dfs(int now){
tin[now]=++cnt;
dfn[cnt]=now;
for(int i=head[now];i;i=e[i].next){
dfs(e[i].to);
}
tout[now]=cnt;
}
struct node{
int l,r;ll sum,cnt;
}seg[maxn*20];
void maketree(int s=1,int t=n,int &now=rt[0]){
now=++size;nd=(node){s,t,0,0};
if(s==t) return ;
maketree(s,mid,nd.l);maketree(mid+1,t,nd.r);
}
void update(int &now,int pre,int k,ll cost,int s=1,int t=n){
now=++size;nd=ndp,nd.sum+=cost,nd.cnt++;
if(s==t) return ;
if(k<=mid)update(nd.l,ndp.l,k,cost,s,mid);
else update(nd.r,ndp.r,k,cost,mid+1,t);
}
ll query(int ndl,int ndr,ll k,int s=1,int t=n){
if(seg[ndr].sum-seg[ndl].sum<=k) return seg[ndr].cnt-seg[ndl].cnt;
if(s==t) return min(seg[ndr].cnt-seg[ndl].cnt,k/pos[s]);
ll sum=seg[seg[ndr].l].sum-seg[seg[ndl].l].sum;
if(k>=sum) return query(seg[ndl].r,seg[ndr].r,k-sum,mid+1,t)+seg[seg[ndr].l].cnt-seg[seg[ndl].l].cnt;
else return query(seg[ndl].l,seg[ndr].l,k,s,mid);
}
#undef mid
int main(){
scanf("%d%lld",&k,&m);
int master;
for(int i=1;i<=k;i++){
scanf("%d%lld%lld",pre+i,cost+i,power+i);
if(pre[i]==0)master=i;
else add(pre[i],i);
pos[i]=cost[i];
}
sort(pos+1,pos+1+k);
n=unique(pos+1,pos+1+k)-(pos+1);
dfs(master);
maketree();
for(int i=1;i<=k;i++){
int id=lower_bound(pos+1,pos+1+n,cost[dfn[i]])-pos;
update(rt[i],rt[i-1],id,cost[dfn[i]]);
}
ll ans=0;
for(int i=1;i<=k;i++){
ans=max(ans,power[i]*query(rt[tin[i]-1],rt[tout[i]],m));
}
printf("%lld\n",ans);
return 0;
}

  

 
  

BZOJ - 2809 dispatching 主席树+dfs序的更多相关文章

  1. BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]

    传送门 题意:查询树上根节点值*子树中权值和$\le m$的最大数量 最大值是多少 求$DFS$序,然后变成区间中和$\le m$最多有几个元素,建主席树,然后权值线段树上二分就行了 $WA$:又把边 ...

  2. 51 nod 1681 公共祖先 (主席树+dfs序)

    1681 公共祖先 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题   有一个庞大的家族,共n人.已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边). 在另 ...

  3. 【BZOJ1803】Spoj1487 Query on a tree III 主席树+DFS序

    [BZOJ1803]Spoj1487 Query on a tree III Description You are given a node-labeled rooted tree with n n ...

  4. bzoj 3772 精神污染 主席树+dfs序

    精神污染 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 637  Solved: 177[Submit][Status][Discuss] Descri ...

  5. 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)

    http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...

  6. BZOJ3772 精神污染 主席树 dfs序

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3772 题意概括 给出一个树,共n个节点. 有m条互不相同的树上路径. 现在让你随机选择2条路径,问 ...

  7. BZOJ5338[TJOI2018]xor——主席树+dfs序

    题目描述 现在有一颗以1为根节点的由n个节点组成的树,树上每个节点上都有一个权值vi. 现在有Q 次操作,操作如下: 1  x y    查询节点x的子树中与y异或结果的最大值 2 x y z     ...

  8. BZOJ3545&3551[ONTAK2010]Peaks——kruskal重构树+主席树+dfs序+树上倍增

    题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只 ...

  9. Codeforces 893F(主席树+dfs序)

    在子树内和距离不超过k是一个二维限制,容易想到主席树,但主席树显然没法查最小值,因为不满足区间可减.kdtree和二维线段树可以干这事,但肯定会T飞.但事实上我们的问题有一个特殊性:对某个点x,查询其 ...

随机推荐

  1. Vue项目搭建

    1.环境搭建 安装node 官网下载安装包,傻瓜式安装:https://nodejs.org/zh-cn/ 安装cnpm npm install -g cnpm --registry=https:// ...

  2. linux下使用sftp【转】

    . 本文完全引用自: http://www.cnblogs.com/kaituorensheng/p/5797753.html 何为sftp sftp是Secure File Transfer Pro ...

  3. HDU 1046(最短路径 **)

    题意是要在一个矩形点阵中求能从一点出发遍历所有点再回到起始点的最短路径长度. 不需要用到搜索什么的,可以走一个“梳子型”即可完成最短路径,而情况可以被分成如下两种: 一.矩形的长或宽中有偶数,则可以走 ...

  4. 细说ORM之Entity FrameWork系列(被替换)

    一. 谈情怀 从第一次接触开发到现在(2018年),接近五年时间了,最初阶段连接数据库,使用的是[SQL语句+ADO.NET],那时候,什么存储过程.什么事务 统统不理解,生硬的将SQL语句传入SQL ...

  5. 905. Sort Array By Parity

    Description Given an array A of non-negative integers, return an array consisting of all the even el ...

  6. 细说log4j之log4j 2.x

    官网:https://logging.apache.org/log4j/2.x/ 1. 主要组件: 从图中可以看出,log4j2中的主要组件为:Filter,Appender,Logger,他们的层次 ...

  7. ueditor 百度编辑器图片上传 接 node.js 及一些前端自定义

    百度编辑器 用node.js 做服务端 demo 大神已整理的 记录一下 以作参考 https://github.com/netpi/ueditor 1. 前端图片工具栏上传input file在这里 ...

  8. springboot(二十一):SpringBoot使用Mybatis注解开发教程-分页-动态sql

    https://blog.csdn.net/KingBoyWorld/article/details/78948304

  9. shell 命令使用笔记

    1.提取字符串中以.ddd结尾的ddd值 result=$(echo "chip86.500" | grep -Eo '\.[0-9]{1,}' | grep -Eo '[0-9] ...

  10. PHP中关于PDO数据访问抽象层的功能操作

    PDO:数据访问抽象层 具有三大特点: 1.可以访问其它数据库  所有数据库都可以 2.具有事务功能 3.带有预处理语句功能(防止SQL注入攻击) 实例操作代码如下: <?php //1.造PD ...