BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆
题目大意:给定一棵树,选定一棵子树中的一些点,薪水和不能超过m,求点的数量*子树根节点的领导能力的最大值
考虑对于每一个节点,我们维护一种数据结构,在当中贪心寻找薪金小的雇佣。
每一个节点暴力重建一定不行。我们考虑可并数据结构。每一个节点将子节点的信息直接合并就可以
能够用启示式合并的Treap。也能够用可并堆
今天特意去学了这玩应0.0 先写了左偏树 然后又写了下随机堆…… 后者速度上更快一些 只是建议从左偏树開始学起
总之平衡树常数各种大就是了0.0
Treap+启示式合并
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #define M 100100
- using namespace std;
- typedef long long ll;
- struct abcd{
- abcd *ls,*rs;
- int key;
- int cnt,siz;
- ll num,sum;
- abcd (ll x,int y);
- void Maintain();
- }*null=new abcd(0,0),*tree[M];
- struct edge{
- int to,next;
- }table[M];
- int head[M],tot;
- int n,root;
- ll m,ans,leadership[M];
- void Add(int x,int y)
- {
- table[++tot].to=y;
- table[tot].next=head[x];
- head[x]=tot;
- }
- abcd :: abcd(ll x,int y)
- {
- ls=rs=null;
- sum=x*y;
- num=x;
- cnt=siz=y;
- key=y?rand():0;
- }
- void abcd :: Maintain()
- {
- siz=ls->siz+rs->siz+cnt;
- sum=ls->sum+rs->sum+num*cnt;
- }
- void Zig(abcd *&x)
- {
- abcd *y=x->ls;
- x->ls=y->rs;
- y->rs=x;
- x=y;
- x->rs->Maintain();
- }
- void Zag(abcd *&x)
- {
- abcd *y=x->rs;
- x->rs=y->ls;
- y->ls=x;
- x=y;
- x->ls->Maintain();
- }
- void Insert(abcd *&x,ll y,int z)
- {
- if(x==null)
- {
- x=new abcd(y,z);
- return ;
- }
- if(y==x->num)
- x->cnt+=z;
- else if(y<x->num)
- {
- Insert(x->ls,y,z);
- if(x->ls->key>x->key)
- Zig(x);
- }
- else
- {
- Insert(x->rs,y,z);
- if(x->rs->key>x->key)
- Zag(x);
- }
- x->Maintain();
- }
- int Query(abcd *x,ll y)
- {
- if(x==null)
- return 0;
- ll temp=x->ls->sum;int re=0;
- if(y<=temp) return Query(x->ls,y);
- re+=x->ls->siz;y-=temp;
- if(y<=x->num*x->cnt)
- return re+y/x->num;
- re+=x->cnt;y-=x->num*x->cnt;
- return re+Query(x->rs,y);
- }
- void Decomposition(abcd *&x,int y)
- {
- if(x==null)
- return ;
- Decomposition(x->ls,y);
- Decomposition(x->rs,y);
- Insert(tree[y],x->num,x->cnt);
- delete x;
- x=null;
- }
- void Tree_DP(int x)
- {
- int i;
- for(i=head[x];i;i=table[i].next)
- {
- Tree_DP(table[i].to);
- if(tree[x]->siz<tree[table[i].to]->siz)
- swap(tree[x],tree[table[i].to]);
- Decomposition(tree[table[i].to],x);
- }
- ans=max(ans,leadership[x]*Query(tree[x],m));
- }
- int main()
- {
- //freopen("2809.in","r",stdin);
- //freopen("2809.out","w",stdout);
- int i,fa;
- ll x;
- cin>>n>>m;
- for(i=1;i<=n;i++)
- {
- scanf("%d%lld%lld",&fa,&x,&leadership[i]);
- if(!fa) root=i;
- else Add(fa,i);
- tree[i]=new abcd(x,1);
- }
- Tree_DP(root);
- cout<<ans<<endl;
- }
- //lld!!
左偏树
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #define M 100100
- using namespace std;
- struct abcd{
- abcd *ls,*rs;
- int num,h;
- abcd(int x);
- }*null=new abcd(0),*tree[M];
- struct edge{
- int to,next;
- }table[M];
- int head[M],tot;
- int n,m,root,leadership[M],sum[M],size[M];
- long long ans;
- void Add(int x,int y)
- {
- table[++tot].to=y;
- table[tot].next=head[x];
- head[x]=tot;
- }
- abcd :: abcd(int x)
- {
- ls=rs=null;
- num=x;
- if(x) h=0;
- else h=-1;
- }
- abcd* Merge(abcd *x,abcd *y)
- {
- if(x==null) return y;
- if(y==null) return x;
- if(x->num<y->num)
- swap(x,y);
- x->rs=Merge(x->rs,y);
- if(x->ls->h<x->rs->h)
- swap(x->ls,x->rs);
- x->h=x->rs->h+1;
- return x;
- }
- void Tree_DP(int x)
- {
- int i;
- for(i=head[x];i;i=table[i].next)
- {
- Tree_DP(table[i].to);
- tree[x]=Merge(tree[x],tree[table[i].to]);
- sum[x]+=sum[table[i].to];
- size[x]+=size[table[i].to];
- while(sum[x]>m)
- {
- sum[x]-=tree[x]->num;
- --size[x];
- tree[x]=Merge(tree[x]->ls,tree[x]->rs);
- }
- }
- ans=max(ans,(long long)size[x]*leadership[x]);
- }
- int main()
- {
- int i,fa,x;
- cin>>n>>m;
- for(i=1;i<=n;i++)
- {
- scanf("%d%d%d",&fa,&x,&leadership[i]);
- if(!fa) root=i;
- else Add(fa,i);
- tree[i]=new abcd(x);
- sum[i]=x;
- size[i]=1;
- }
- Tree_DP(root);
- cout<<ans<<endl;
- }
随机堆
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #define M 100100
- using namespace std;
- struct abcd{
- abcd *ls,*rs;
- int num;
- abcd(int x);
- }*null=new abcd(0),*tree[M];
- struct edge{
- int to,next;
- }table[M];
- bool son;
- int head[M],tot;
- int n,m,root,leadership[M],sum[M],size[M];
- long long ans;
- void Add(int x,int y)
- {
- table[++tot].to=y;
- table[tot].next=head[x];
- head[x]=tot;
- }
- abcd :: abcd(int x)
- {
- ls=rs=null;
- num=x;
- }
- abcd* Merge(abcd *x,abcd *y)
- {
- if(x==null) return y;
- if(y==null) return x;
- if(x->num<y->num)
- swap(x,y);
- if(son^=1)
- x->rs=Merge(x->rs,y);
- else
- x->ls=Merge(x->ls,y);
- return x;
- }
- void Tree_DP(int x)
- {
- int i;
- for(i=head[x];i;i=table[i].next)
- {
- Tree_DP(table[i].to);
- tree[x]=Merge(tree[x],tree[table[i].to]);
- sum[x]+=sum[table[i].to];
- size[x]+=size[table[i].to];
- while(sum[x]>m)
- {
- sum[x]-=tree[x]->num;
- --size[x];
- tree[x]=Merge(tree[x]->ls,tree[x]->rs);
- }
- }
- ans=max(ans,(long long)size[x]*leadership[x]);
- }
- int main()
- {
- int i,fa,x;
- cin>>n>>m;
- for(i=1;i<=n;i++)
- {
- scanf("%d%d%d",&fa,&x,&leadership[i]);
- if(!fa) root=i;
- else Add(fa,i);
- tree[i]=new abcd(x);
- sum[i]=x;
- size[i]=1;
- }
- Tree_DP(root);
- cout<<ans<<endl;
- }
BZOJ 2809 APIO2012 dispatching Treap+启示式合并 / 可并堆的更多相关文章
- BZOJ 2809 APIO 2012 dispatching 平衡树启示式合并
题目大意:给出一棵树,每个节点有两个值,各自是这个忍者的薪水和忍者的领导力.客户的惬意程度是这个点的领导力乘可以取得人数.前提是取的人的薪水总和不超过总的钱数. 思路:仅仅能在子树中操作.贪心的想,我 ...
- BZOJ 2809: [Apio2012]dispatching( 平衡树 + 启发式合并 )
枚举树上的每个结点做管理者, 贪心地取其子树中薪水较低的, 算出这个结点为管理者的满意度, 更新答案. 用平衡树+启发式合并, 时间复杂度为O(N log²N) ------------------- ...
- bzoj 2809: [Apio2012]dispatching -- 可并堆
2809: [Apio2012]dispatching Time Limit: 10 Sec Memory Limit: 128 MB Description 在一个忍者的帮派里,一些忍者们被选中派 ...
- BZOJ 2809: [Apio2012]dispatching(左偏树)
http://www.lydsy.com/JudgeOnline/problem.php?id=2809 题意: 思路:最简单的想法就是枚举管理者,在其子树中从薪水低的开始选起,但是每个节点都这样处理 ...
- BZOJ 2809 [Apio2012]dispatching(斜堆+树形DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2809 [题目大意] 给出一棵树,求出每个点有个权值,和一个乘算值,请选取一棵子树, 并 ...
- bzoj 2809: [Apio2012]dispatching
#include<cstdio> #include<algorithm> #define M 1000005 using namespace std; long long an ...
- BZOJ 2809: [Apio2012]dispatching [斜堆]
题意:主席树做法见上一题 我曾发过誓再也不写左偏树(期末考试前一天下午5个小时没写出棘手的操作) 于是我来写斜堆啦 从叶子往根合并,维护斜堆就行了 题目连拓扑序都给你了... 说一下斜堆的操作: 合并 ...
- BZOJ 2809: [Apio2012]dispatching(可并堆 左偏树板题)
这道题只要读懂题目一切好说. 给出nnn个点的一棵树,每一个点有一个费用vvv和一个领导力aaa,给出费用上限mmm.求下面这个式子的最大值ax∗∣S∣ ( S⊂x的子树, ∑iv[i]≤m )\la ...
- BZOJ 2809: [Apio2012]dispatching [主席树 DFS序]
传送门 题意:查询树上根节点值*子树中权值和$\le m$的最大数量 最大值是多少 求$DFS$序,然后变成区间中和$\le m$最多有几个元素,建主席树,然后权值线段树上二分就行了 $WA$:又把边 ...
随机推荐
- 多文件上传组件FineUploader使用心得
原文 多文件上传组件FineUploader使用心得 做Web开发的童鞋都知道,需要经常从客户端上传文件到服务端,当然,你可以使用<input type="file"/> ...
- 12.5.3 UNIVERSAL:最终的祖先类:
<pre name="code" class="html">12.5.3 UNIVERSAL:最终的祖先类: 你可以把 UNIVERSAL 看作最终 ...
- __autoload()方法
php中__autoload()方法详解 PHP在魔术函数__autoload()方法出现以前,如果你要在一个程序文件中实例化100个对象,那么你必须用include或者require包含进来100个 ...
- js数组基础整理
首页: 主要整理了一下数组中常用的一些基础知识,代码都是自己手敲,有不对的地方希望能指出,目前只有4篇,后续会不断的增加这一板块. 由于少于100字不能发所以把一些最基本的创建数组也写上. // 创建 ...
- delphi中左右翻转窗体(修改EXStyle)
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Form ...
- HTML5 Canvas中9宫格的坑
近期小鸟情人游戏上了手机qq空间,一个3岁的游戏来了她的第二春.为了能有更好的表现,我们对其进行了一次改版. 改版当中一项就是对原来的弹出框样式进行改进.将大块木板材质改成纯色(边框为圆角金属材质)样 ...
- 男性在下一100层【第三层】——高仿手机银行client接口
前言: 从<男性在下一100层>系列博文[二楼]现在出版了整整三个月后,.从上述观点和这么多朋友的意见还是比较喜欢真实类的博文. 毕竟我们都叫"攻城狮".所以要看是否这 ...
- VS关闭Browser Link
原文:VS关闭Browser Link 这是VS2013的一个新功能,叫Browser Link,基于SignalR. 它可以实现VS IDE和你的程序的双向通讯,在IDE编辑代码即刻将修改发送到浏览 ...
- 我在知乎上关于Laser200/310电脑的文章。
我是30年前从Laser-310起步的,我来回答这个问题. 主要硬件规格: CPU:Z-80A/4.7MHz主频 16K RAM + 2K Video RAM 16K ROM 磁带输出:波特率300 ...
- SAP屏幕框架的创建
1.创建包括文本的基本框架 REPORT ztest_sum. TABLES:mara,syst. WITH FRAME TITLE mytitle. "mytitle是框架上的文本 ) A ...