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. Android笔记-1

    1.点击按钮出现小窗口(响应事件) 配置方式: Activity_main.xml文件中:<Button (输入)android: onClick=”test1” /> MainActiv ...

  2. 网桥 以及 IEEE802.1D 生成树协议

    (一)网桥 网桥是一个layer 2设备,能够连接两个不同的网段. 如图

  3. JAVA中处理事务的程序--多条更新SQL语句的执行(包括回滚)

    在与数据库操作时,如果执行多条更新的SQL语句(如:update或insert语句),在执行第一条后如果出现异常或电脑断电, 则后面的SQL语句执行不了,这时候设定我们自己提交SQL语句,不让JDBC ...

  4. java中注解的使用与实例

    1.spring中的一段代码: @Target(ElementType.PARAMETER)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @ ...

  5. 深入理解JAVA I/O系列二:字节流详解

    流的概念 JAVA程序通过流来完成输入/输出.流是生产或消费信息的抽象,流通过JAVA的输入输出与物理设备链接,尽管与它们链接的物理设备不尽相同,所有流的行为具有相同的方式.这样就意味一个输入流能够抽 ...

  6. jmeter body 中文显示为乱码解决

    这种情况在jmeter3.0的版本中才会产生,注意:这不是乱码,而是由于3.0中优化body data后,使用默认的字体(Consolas)不支持汉字的显示.这样的情况可以这样调整:进入jmeter. ...

  7. 实测 | 转型微服务,这4大工具谁是API网关性能最优?

    转自:http://www.servicemesh.cn/?/article/45 作者:Turgay Çelik 翻译:钟毅(Drew Zhong) 原文:Comparing API Gateway ...

  8. MySQL数据库中varchar与char类型的区别

    在数据库中建表时,需要给数据定义一个数据库中的数据库类型,当需要给String类型定义一个数据库中的类型时,可以看见有两个选择,一个是varchar,另一个是char,有很多人不清楚两者的区别,包括自 ...

  9. maven依赖jar包时版本冲突的解决

    https://blog.csdn.net/sinat_39789638/article/details/78005945 共有四种解决方式: 1.第一声明优先原则: 在pom.xml配置文件中,如果 ...

  10. centOS基本操作和命令(更新)

    1.文字输入和图形界面切换 CTRL+ALT+(F1~F6)为切换至文字输入,分别对应六个不同输入界面,可用以不同账号:CTRL+ALT+F7为切换至图形界面 2.修改时区 date -R date ...