题目大意:给出一棵树,每个节点有两个值,各自是这个忍者的薪水和忍者的领导力。客户的惬意程度是这个点的领导力乘可以取得人数。前提是取的人的薪水总和不超过总的钱数。

思路:仅仅能在子树中操作。贪心的想,我们仅仅要这个子树中cost最小的那些点就能够了。

所以就深搜一次。每到一个节点上。把自己和全部子节点的平衡树启示式和并,然后保留不超过总钱数的人数。统计。数据范围比較大,能开long long的地方不要吝啬。

PS:吐槽一下,一開始这个题一直TTT。我以为是我常数写的太大了。别人都用左偏堆写。是不是平衡树已经成为了时代的眼泪了。

。。

后来我搞到了測点。跑了一下第一组数据等了1分多钟都没出解。

我感觉我又要重写了。就出去转转。十分钟之后我回来发现竟然出解了。并且竟然还对了!!

然后我细致看了一遍程序。

。发现是启示式合并写反了。。。。写反了。。。反了。。。

了。。。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
using namespace std; struct Complex{
long long cost,leader;
}point[MAX]; struct Treap{
int random,size,cnt;
long long val,sum;
Treap *son[2]; Treap(long long _) {
val = sum = _;
size = cnt = 1;
random = rand();
son[0] = son[1] = NULL;
}
int Compare(long long x) {
if(x == val) return -1;
return x > val;
}
void Maintain() {
size = cnt;
sum = val * cnt;
if(son[0] != NULL) size += son[0]->size,sum += son[0]->sum;
if(son[1] != NULL) size += son[1]->size,sum += son[1]->sum;
}
}*tree[MAX]; long long points,money;
int head[MAX],total;
int next[MAX << 1],aim[MAX << 1]; long long ans; inline void Add(int x,int y)
{
next[++total] = head[x];
aim[total] = y;
head[x] = total;
} inline void Rotate(Treap *&a,bool dir)
{
Treap *k = a->son[!dir];
a->son[!dir] = k->son[dir];
k->son[dir] = a;
a->Maintain(),k->Maintain();
a = k;
} inline void Insert(Treap *&a,long long x)
{
if(a == NULL) {
a = new Treap(x);
return ;
}
int dir = a->Compare(x);
if(dir == -1) ++a->cnt;
else {
Insert(a->son[dir],x);
if(a->son[dir]->random > a->random)
Rotate(a,!dir);
}
a->Maintain();
} inline int FindMax(Treap *a)
{
return a->son[1] == NULL ? a->val:FindMax(a->son[1]);
} inline void Delete(Treap *&a,long long x)
{
int dir = a->Compare(x);
if(dir != -1) Delete(a->son[dir],x);
else {
if(a->cnt > 1) --a->cnt;
else {
if(a->son[0] == NULL) a = a->son[1];
else if(a->son[1] == NULL) a = a->son[0];
else {
bool _ = (a->son[0]->random > a->son[1]->random);
Rotate(a,_);
Delete(a->son[_],x);
}
}
}
if(a != NULL) a->Maintain();
} void Transfrom(Treap *&from,Treap *&aim)
{
if(from == NULL) return ;
Transfrom(from->son[0],aim);
Transfrom(from->son[1],aim);
for(int i = 1; i <= from->cnt; ++i)
Insert(aim,from->val);
delete from;
from = NULL;
} void DFS(int x)
{
tree[x] = new Treap(point[x].cost);
if(point[x].cost <= money)
ans = max(ans,(long long)point[x].leader);
if(!head[x])
return ;
for(int i = head[x]; i; i = next[i]) {
DFS(aim[i]);
if(tree[x]->size < tree[aim[i]]->size)
swap(tree[x],tree[aim[i]]);
Transfrom(tree[aim[i]],tree[x]);
}
while(tree[x]->sum > money)
Delete(tree[x],FindMax(tree[x]));
ans = max(ans,(long long)tree[x]->size * point[x].leader);
} int main()
{
cin >> points >> money;
for(int x,i = 1; i <= points; ++i) {
scanf("%d%lld%lld",&x,&point[i].cost,&point[i].leader);
Add(x,i);
}
DFS(0);
cout << ans << endl;
return 0;
}

BZOJ 2809 APIO 2012 dispatching 平衡树启示式合并的更多相关文章

  1. BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆

    题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值 考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣. 每一个节点暴力重建一定 ...

  2. BZOJ 2733 HNOI 2012 永无乡 平衡树启示式合并

    题目大意:有一些岛屿,一開始由一些无向边连接. 后来也有不断的无向边增加,每个岛屿有个一独一无二的重要度,问随意时刻的与一个岛屿联通的全部岛中重要度第k大的岛的编号是什么. 思路:首先连通性一定要用并 ...

  3. bzoj 2809 左偏树\平衡树启发式合并

    首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节 ...

  4. 【BZOJ 2809】 [Apio2012]dispatching

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

  5. APIO 2012 派遣(可并堆)

    APIO 2012 派遣(可并堆) 给定一棵N个点的树和M,每个点有两个权值ai,bi,每次可以选择一个点x,然后在这个点的子树中选若干点(可以不选自己),使得这些点的\(\sum b_i<=M ...

  6. 【BZOJ 2809】【APIO 2012】dispatching

    昨天晚上zyf神犇问我的题,虽然我太弱参加不了APIO但也做一做吧. 用小数据拍了无数次总是查不出错来,交上去就WA,后来用国内数据测发现是主席树上区间相减的值没有用long long存,小数据真是没 ...

  7. 「BZOJ 2809」「APIO 2012」Dispatching「启发式合并」

    题意 给定一个\(1\)为根的树,每个点有\(c,w\)两个属性,你需要从某个点\(u\)子树里选择\(k\)个点,满足选出来的点\(\sum_{i=1}^k w(i)\leq m\),最大化\(k\ ...

  8. BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )

    枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...

  9. bzoj 2809: [Apio2012]dispatching -- 可并堆

    2809: [Apio2012]dispatching Time Limit: 10 Sec  Memory Limit: 128 MB Description 在一个忍者的帮派里,一些忍者们被选中派 ...

随机推荐

  1. python--基础数据类型的补充与深浅copy

    一 . join的用法 lst =['吴彦祖','谢霆锋','刘德华'] s = '_'.join(lst) print(s) # 吴彦祖_谢霆锋_刘德华 # join() "*" ...

  2. shell-code-5-函数

    # 函数必须在使用前定义 # 如果不写return,将以最后一条命令运行结果,作为返回值. return后跟数值n(0-255) myFistFunc(){ read a read b return ...

  3. (原)剑指offer变态跳台阶

    变态跳台阶 时间限制:1秒空间限制:32768K 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级.求该青蛙跳上一个n级的台阶总共有多少种跳法.   分析一下明天是个斐波那契 ...

  4. 牛客网暑期ACM多校训练营(第六场) J Heritage of skywalkert(数论, eth_element)

    链接: https://www.nowcoder.com/acm/contest/144/J 题意: 给定一个函数, 求它n次结果中任意两次的lcm最大值 分析: 首先要看出这个函数并没有什么含义, ...

  5. ACM-ICPC 2018 沈阳赛区网络预赛 K. Supreme Number

    A prime number (or a prime) is a natural number greater than 11 that cannot be formed by multiplying ...

  6. sql优化工具--美团SQLAdvisor

    美团点评SQL优化工具SQLAdvisor开源 介绍 在数据库运维过程中,优化 SQL 是 DBA 团队的日常任务.例行 SQL 优化,不仅可以提升程序性能,还能够降低线上故障的概率. 目前常用的 S ...

  7. HDU 3341 Lost's revenge

    Lost's revenge Time Limit: 5000ms Memory Limit: 65535KB This problem will be judged on HDU. Original ...

  8. 九度oj 题目1140:八皇后

    题目描述: 会下国际象棋的人都很清楚:皇后可以在横.竖.斜线上不限步数地吃掉其他棋子.如何将8个皇后放在棋盘上(有8 * 8个方格),使它们谁也不能被吃掉!这就是著名的八皇后问题. 对于某个满足要求的 ...

  9. CSS参数介绍

    原文发布时间为:2008-08-03 -- 来源于本人的百度文章 [由搬家工具导入] 行高       line-height: 16px 宽度       (具体位置)-width: 16px 文字 ...

  10. 【转】UITableViewCell自适应高度 UILabel自适应高度和自动换行

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {     ...