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 在一个忍者的帮派里,一些忍者们被选中派 ...
随机推荐
- PHP方法之 substr
简单描述: substr 主要用于字符串的截取,但是不适用于中文字符串,易出现乱码,中文字符串可使用mbstring. 方法申明: substr(string,start,length) string ...
- boot_mem分配器
#define alloc_bootmem_low_pages(x) \ __alloc_bootmem_low(x, PAGE_SIZE, ) void * __init __alloc_bootm ...
- Linux中断底半部机制
参考: Linux下半部处理之软中断 linux中断底半部机制 <深入理解Linux内核>软中断/tasklet/工作队列 软中断和tasklet介绍 详解操作系统中断 Linux内核:中 ...
- uboot的Makefile裁剪(针对飞思卡尔的mx6系列)
VERSION = 2009PATCHLEVEL = 08SUBLEVEL =EXTRAVERSION =ifneq "$(SUBLEVEL)" ""U_BOO ...
- 九度oj 题目1139:最大子矩阵
题目描述: 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 0 9 2 -6 2 -4 1 ...
- linux删除N天前的文件
列出一天之前的文件的属性用下面的命令:find . ! -mtime -1 -print |xargs ls -lfind . -mtime +1 要删除文件的话用下面的命令:find . ! -mt ...
- BZOJ 4650 [Noi2016]优秀的拆分 ——后缀数组
我们只需要统计在某一个点开始的形如$AA$字符串个数,和结束的个数相乘求和. 首先枚举循环节的长度L.即$\mid (A) \mid=L$ 然后肯定会经过s[i]和[i+L]至少两个点. 然后我们可以 ...
- 2013 年 acm 长春现场赛
A - Hard Code Hdu 4813 题目大意:给你一坨字符串,让你输出其栅栏密码的解码形式 思路:水题模拟 #include<iostream> #include<cstd ...
- mybatis学习(三)——接口式编程
对于上一节中的查询我们还可以通过接口的方式进行编程,开发环境和上一节一样 1.全局配置文件mybatis_config.xml(和上一节一样) <?xml version="1.0&q ...
- weixin-api生成二维码
二维码长链接转成短链接(减少扫描时间和提高成功率) 微信返回正确的二维码的结果,参数有个url,即二维码图片解析后的地址,也可以根据此URL生成需要的二维码图片,而不需要通过ticket去换取图片了 ...