bzoj 2809: [Apio2012]dispatching

http://www.lydsy.com/JudgeOnline/problem.php?id=2809

Description

在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为 Master。除了 Master以外,每名忍者都有且仅有一个上级。为保密,同时增强忍者们的领导力,所有与他们工作相关的指令总是由上级发送给他的直接下属,而不允许通过其他的方式发送。现在你要招募一批忍者,并把它们派遣给顾客。你需要为每个被派遣的忍者 支付一定的薪水,同时使得支付的薪水总额不超过你的预算。另外,为了发送指令,你需要选择一名忍者作为管理者,要求这个管理者可以向所有被派遣的忍者 发送指令,在发送指令时,任何忍者(不管是否被派遣)都可以作为消息的传递 人。管理者自己可以被派遣,也可以不被派遣。当然,如果管理者没有被排遣,就不需要支付管理者的薪水。你的目标是在预算内使顾客的满意度最大。这里定义顾客的满意度为派遣的忍者总数乘以管理者的领导力水平,其中每个忍者的领导力水平也是一定的。写一个程序,给定每一个忍者 i的上级 Bi,薪水Ci,领导力L i,以及支付给忍者们的薪水总预算 M,输出在预算内满足上述要求时顾客满意度的最大值。
 
1  ≤N ≤ 100,000 忍者的个数;
1  ≤M ≤ 1,000,000,000 薪水总预算; 
 
0  ≤Bi < i  忍者的上级的编号;
1  ≤Ci ≤ M                     忍者的薪水;
1  ≤Li ≤ 1,000,000,000             忍者的领导力水平。

Input

从标准输入读入数据。
 
第一行包含两个整数 N M,其中 N表示忍者的个数,M表示薪水的总预算。
 
接下来 N行描述忍者们的上级、薪水以及领导力。其中的第 i 行包含三个整 Bi , C i , L i分别表示第i个忍者的上级,薪水以及领导力。Master满足B i = 0并且每一个忍者的老板的编号一定小于自己的编号 Bi < i

Output

输出一个数,表示在预算内顾客的满意度的最大值。

Sample Input

5 4
0 3 3
1 3 5
2 2 2
1 2 4
2 3 1

Sample Output

6

HINT

如果我们选择编号为 1的忍者作为管理者并且派遣第三个和第四个忍者,薪水总和为 4,没有超过总预算。

因为派遣了2 个忍者并且管理者的领导力为 3,用户的满意度为 6  ,是可以得到的用户满意度的最大值。

题目剖析:

ans=领导力*个数

领导力:枚举每个忍者

个数:当然是需要薪水少的先派遣啦

所以,节点的领导力为a,在以这个节点为根的子树中(包括这个节点),从小到大选尽可能多的节点s,满足节点的薪水和<=总预算,最大化a*s

这道题还可以用左偏树来做,但蒟蒻一枚只会主席树 ,所以这里只写主席树做法

推荐黄学长的博客,维护子树大根堆,用可并堆将时间复杂度降为nlongn http://hzwer.com/5682.html

数据结构:主席树

辅助:dfs序(开始没想到)

以忍者的dfs序为下标,薪水为区间建立主席树

首先说说dfs序

1、为什么需要dfs序?

因为派遣忍者的范围是以这个忍者为根的子树。

假设当前节点为i,遍历到时令 in[i]=a, 表示i是第a个被遍历。以i为节点的子树遍历完后,令out[i]=b,b为当前所有已遍历节点总数

那么这个节点可以派遣的范围是dfs序[a,b](包括a,b)之间的忍者

所dfs序的作用是锁定查找区间

2、如何构造dfs序?(自己也没想到)

令t表示当前已遍历节点总数,每遍历一个节点t++,设当前节点为i,遍历到i是in[i]=t,i退出时out[i]=t

在构造dfs序时,顺便记录下dfs序为i的忍者的薪水、领导力,然后按照dfs序在主席树中插入节点

最后是查找

枚举每个忍者,查找他的派遣范围最多能派遣多少个忍者

如果做过[CQOI2015]任务查询系统,会知道那道题在查询查到叶子节点时,对答案的贡献是sum[l]/count[l]*k

本题查询的是数量,到叶子节点时有没有坑呢?

有。叶子节点对答案有贡献的忍者数量应该是 min(薪水预算/派遣这个节点的忍者所需薪水,这个节点的忍者个数)

这里的节点是主席树中以薪水为区间建立的节点

还有就是要注意答案用long long

#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
int n,m,money[N],lead[N],front[N],next[N];
int hash[N],cnt_money;
int in[N],out[N],t;
int root[N],tot,lc[N*],rc[N*],cnt[N*];
long long sum[N*],ans,dispatch;
struct node
{
int mon,lea;
}e[N];
inline void add(int u,int v)
{
next[v]=front[u];
front[u]=v;
}
inline int dfs(int r)
{
in[r]=++t;
e[t].lea=lead[r];e[t].mon=hash[r];
if(front[r])
for(int i=front[r];i;i=next[i])
dfs(i);
out[r]=t;
}
void discrete()
{
sort(money+,money+n+);
cnt_money=unique(money+,money+n+)-(money+);
for(int i=;i<=n;i++) hash[i]=lower_bound(money+,money+cnt_money+,hash[i])-money;
}
inline void insert(int pre,int & now,int l,int r,int w)
{
sum[now=++tot]=sum[pre]+money[w];
cnt[now]=cnt[pre]+;
if(l==r) return;
int mid=l+r>>;
if(w<=mid)
{
rc[now]=rc[pre];
insert(lc[pre],lc[now],l,mid,w);
}
else
{
lc[now]=lc[pre];
insert(rc[pre],rc[now],mid+,r,w);
}
}
inline int query(int x,int y,int l,int r,long long k)
{
if(l==r) return min(k/(long long)money[l],(long long)(cnt[y]-cnt[x]));
int mid=l+r>>;
long long tmp=sum[lc[y]]-sum[lc[x]];
if(k<=tmp) return query(lc[x],lc[y],l,mid,k);
else return cnt[lc[y]]-cnt[lc[x]]+query(rc[x],rc[y],mid+,r,k-tmp);
}
int main()
{
scanf("%d%lld",&n,&m);
int b,c,l;
for(int i=;i<=n;i++)
{
scanf("%d%d%d",&b,&money[i],&lead[i]);
hash[i]=money[i];
add(b,i);
}
discrete();
dfs(front[]);
for(int i=;i<=n;i++) insert(root[i-],root[i],,cnt_money,e[i].mon);
for(int i=;i<=n;i++)
{
int l=in[i],r=out[i];//l:节点i的dfs序,r节点i可以派遣的最靠后的忍者的dfs序
dispatch=query(root[l-],root[r],,cnt_money,m);
ans=max(ans,(long long)lead[i]*dispatch);
}
printf("%lld",ans);
}

这道题做的时候

1、没有想到用dfs序锁定查找区间

2、ans=max(忍者的领导力*派遣忍者个数),没有想到可以枚举每个忍者,这样就解决了领导力的问题。对答案的分解能力欠缺

3、答案没用long long,开始做的时候还想着答案用long long,想先写出来过了样例后再改,结果忘了

4、查询时,如果当前区间为[x,y],要到节点的右孩子去查询,返回的答案应是区间左右端点左孩子的cnt差,而不是y的cnt。这里与任务查询系统混了,因为任务查询系统查询的区间是[0,y],0可以省略,所以可以直接用y的cnt、sum

[Apio2012]dispatching 主席树做法的更多相关文章

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

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

  2. Luogu P1552 [APIO2012]派遣 主席树

    题目链接 Click Here 这个题好像大多数人用的都是左偏树啊?这里我来贡献一发主席树的解法. 把题目中的问题抽象出来,其实就是询问每一个点的子树中,工资前\(tot_i\)大的点,使它们的和满足 ...

  3. BZOJ - 2809 dispatching 主席树+dfs序

    在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同时增强忍者们的 ...

  4. SPOJ DQUERY D-query(主席树)

    题目 Source http://www.spoj.com/problems/DQUERY/en/ Description Given a sequence of n numbers a1, a2, ...

  5. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  6. 初识主席树_Prefix XOR

    主席树刚接触觉得超强,根本看不懂,看了几位dalao的代码后终于理解了主席树. 先看一道例题:传送门 题目大意: 假设我们预处理出了每个数满足条件的最右边界. 先考虑暴力做法,直接对x~y区间暴枚,求 ...

  7. BZOJ 2161 布娃娃 (主席树)

    题面 想了一个主席树做法 我们把每个区间的两个端点拆开 对$L,R$分别从小到大排序,分别从左到右依次把对应标号的$c_{i}$插入到权值主席树里 每次查询$p_{i}$,在排序后的$L,R$数组上分 ...

  8. LOJ 6435 「PKUSC2018」星际穿越——DP+倍增 / 思路+主席树

    题目:https://loj.ac/problem/6435 题解:https://www.cnblogs.com/HocRiser/p/9166459.html 自己要怎样才能想到怎么做呢…… dp ...

  9. zoj2112 Dynamic Rankings (主席树 || 树套树)

    The Company Dynamic Rankings has developed a new kind of computer that is no longer satisfied with t ...

随机推荐

  1. 作业6 团队项目之(开始第一个Sprint)

    一.模仿并超越--类似应用. 五个app:1.四则运算小学堂(500-999次下载 3.57M) 2.小学生算术练习(9000+次下载 232K) 3.小学生加减题生成练习工具(2万-3万次下载 1. ...

  2. 【CS231N】7、卷积神经网络

    一.疑问 1. assignments2 在代码文件FullyConnectedNets.ipynd 中,有代码如下: # Test the affine_forward function num_i ...

  3. 【搜索】POJ-3669 BFS

    一.题目 Description Bessie hears that an extraordinary meteor shower is coming; reports say that these ...

  4. sql中exists和not exists的用法

    该文转载自:http://www.cnblogs.com/mytechblog/articles/2105785.html sql中exists,not exists的用法 exists : 强调的是 ...

  5. 个人作业-Week 3

    案例分析:必应词典 IOS客户端 调研&评测 一.功能性bug bug 1: 症状:在使用拍照翻译这一功能时,只能对图片中的句子逐行进行翻译.即一个中间有换行的句子会被当成两个句子进行翻译. ...

  6. 蜗牛慢慢爬 LeetCode 5.Longest Palindromic Substring [Difficulty: Medium]

    题目 Given a string s, find the longest palindromic substring in s. You may assume that the maximum le ...

  7. 如何快速地编写和运行一个属于自己的 MapReduce 例子程序

    大数据的时代, 到处张嘴闭嘴都是Hadoop, MapReduce, 不跟上时代怎么行? 可是对一个hadoop的新手, 写一个属于自己的MapReduce程序还是小有点难度的, 需要建立一个mave ...

  8. eclipse+IDEA快捷键记录

    Eclipse中自动获取 IDEA中:ctrl+alt+v==alt+shift+l 其它   (有些地方前面的C代表Ctrl .S代表Shift.A代表Alt) Ctrl+Shift+F       ...

  9. Netty基础系列(3) --彻底理解NIO

    前言 上一节中我们提到了同步异步与阻塞非阻塞的区别,知道了同步并不等于阻塞.而本节的主角NIO是一种同步非阻塞的I/O模型,并且是I/O多路复用模型.NIO在java中被称为 New I/O.它并不能 ...

  10. BZOJ 2668: [cqoi2012]交换棋子

    2668: [cqoi2012]交换棋子 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1112  Solved: 409[Submit][Status ...