博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ 2809 APIO 2012 dispatching 平衡树启示式合并
阅读量:6544 次
发布时间:2019-06-24

本文共 2847 字,大约阅读时间需要 9 分钟。

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

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

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

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

。。

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

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

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

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

了。。。

CODE:

#include 
#include
#include
#include
#define MAX 100010using 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; }

转载地址:http://zwldo.baihongyu.com/

你可能感兴趣的文章
-----二叉树的遍历-------
查看>>
ACM北大暑期课培训第一天
查看>>
F. Multicolored Markers(数学思维)
查看>>
Centos7安装搜狗输入法
查看>>
nodjs html 转 pdf
查看>>
Python字典
查看>>
ofstream 的中文目录问题
查看>>
Android存储方式之SQLite的使用
查看>>
洛谷P1287 盒子与球 数学
查看>>
Bootstrap vs Foundation如何选择靠谱前端框架
查看>>
与、或、异或、取反、左移和右移
查看>>
vue常用的指令
查看>>
matlab练习程序(随机游走图像)
查看>>
Linux命令行下运行java.class文件
查看>>
input文本框实现宽度自适应代码实例
查看>>
protocol buffers的编码原理
查看>>
行为型设计模式之命令模式(Command)
查看>>
减少死锁的几个常用方法
查看>>
HDFS 核心原理
查看>>
正确配置jstl的maven依赖,jar包冲突的问题终于解决啦
查看>>