BZOJ 2809 APIO 2012 dispatching 平衡树启示式合并
题目大意:给出一棵树,每个节点有两个值,各自是这个忍者的薪水和忍者的领导力。客户的惬意程度是这个点的领导力乘可以取得人数。前提是取的人的薪水总和不超过总的钱数。
思路:仅仅能在子树中操作。贪心的想,我们仅仅要这个子树中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 平衡树启示式合并的更多相关文章
- BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆
题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值 考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣. 每一个节点暴力重建一定 ...
- BZOJ 2733 HNOI 2012 永无乡 平衡树启示式合并
题目大意:有一些岛屿,一開始由一些无向边连接. 后来也有不断的无向边增加,每个岛屿有个一独一无二的重要度,问随意时刻的与一个岛屿联通的全部岛中重要度第k大的岛的编号是什么. 思路:首先连通性一定要用并 ...
- bzoj 2809 左偏树\平衡树启发式合并
首先我们对于一颗树,要选取最多的节点使得代价和不超过m,那么我们可以对于每一个节点维护一个平衡树,平衡树维护代价以及代价的和,那么我们可以在logn的时间内求出这个子树最多选取的节点数,然后对于一个节 ...
- 【BZOJ 2809】 [Apio2012]dispatching
Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级. ...
- APIO 2012 派遣(可并堆)
APIO 2012 派遣(可并堆) 给定一棵N个点的树和M,每个点有两个权值ai,bi,每次可以选择一个点x,然后在这个点的子树中选若干点(可以不选自己),使得这些点的\(\sum b_i<=M ...
- 【BZOJ 2809】【APIO 2012】dispatching
昨天晚上zyf神犇问我的题,虽然我太弱参加不了APIO但也做一做吧. 用小数据拍了无数次总是查不出错来,交上去就WA,后来用国内数据测发现是主席树上区间相减的值没有用long long存,小数据真是没 ...
- 「BZOJ 2809」「APIO 2012」Dispatching「启发式合并」
题意 给定一个\(1\)为根的树,每个点有\(c,w\)两个属性,你需要从某个点\(u\)子树里选择\(k\)个点,满足选出来的点\(\sum_{i=1}^k w(i)\leq m\),最大化\(k\ ...
- BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )
枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...
- bzoj 2809: [Apio2012]dispatching -- 可并堆
2809: [Apio2012]dispatching Time Limit: 10 Sec Memory Limit: 128 MB Description 在一个忍者的帮派里,一些忍者们被选中派 ...
随机推荐
- Python9-装饰器-day11
import time def timmer(f): #装饰器函数 def inner(): start = time.time() ret = f() #被装饰的函数 end = time.time ...
- JavaScript正则表达式-非捕获性分组
非捕获性分组定义子表达式可以作为整体被修饰但是子表达式匹配结果不会被存储. 非捕获性分组通过将子表达式放在"?:"符号后. str = "img1.jpg,img2.jp ...
- Redis 数据类型分析 字符串 哈希 列表 集合 有序集合 优缺点 分析 注意事项 存储结构
一.提高Redis使用性能秘诀 KEY尽量少的原则,能放在1个KEY的就放入1个KEY,KEY开销很大尽量减少与Redis发生的交互次数,能批量的就批量,能事务.管道的就事务.管道从业务架构分析确定使 ...
- Charlie's Change(完全背包记录路径)
Charlie is a driver of Advanced Cargo Movement, Ltd. Charlie drives a lot and so he often buys coffe ...
- 用KMP征服循环节问题
以前我还是写过KMP的文章的 现在我们可以求一下循环节啊 Slot Machines Gym - 101667I #include<bits/stdc++.h> using namespa ...
- 转自kuangbin的AC自动机(赛前最后一博)
有了KMP和Trie的基础,就可以学习神奇的AC自动机了.AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配. AC自动机 其实 就是创建了一个状态的转移图,思想很 ...
- 九度oj 题目1533:最长上升子序列
题目描述: 给定一个整型数组, 求这个数组的最长严格递增子序列的长度. 譬如序列1 2 2 4 3 的最长严格递增子序列为1,2,4或1,2,3.他们的长度为3. 输入: 输入可能包含多个测试案例. ...
- [BZOJ1574] [Usaco2009 Jan]地震损坏Damage(贪心 + dfs)
传送门 告诉你一些点不能到达1,由于是双向边,也就是1不能到达那些点 那么从1开始dfs,如果当前点能到达不能到达的点,那么当前点就是损坏的. #include <cstdio> #inc ...
- FZU 2020 :组合 【lucas】
Problem Description 给出组合数C(n,m), 表示从n个元素中选出m个元素的方案数.例如C(5,2) = 10, C(4,2) = 6.可是当n,m比较大的时候,C(n,m)很大! ...
- C++函数传递指向指针的指针的应用
传递指向指针的引用假设我们想编写一个与前面交换两个整数的 swap 类似的函数,实现两个指针的交换.已知需用 * 定义指针,用 & 定义引用.现在,问题在于如何将这两个操作符结合起来以获得指向 ...