[APIO2012]派遣 洛谷P1552 bzoj2809 codevs1763
http://www.codevs.cn/problem/1763/
https://www.lydsy.com/JudgeOnline/problem.php?id=2809
https://www.luogu.org/problemnew/show/P1552
http://210.33.19.101/problem/2182
用线段树合并,值域线段树维护可重集合,线段树每个节点维护一个sum表示当前集合中,所有在范围[l,r](这个点的值域区间)内的数的和;每个点从其子节点合并;查询就根据左子节点sum与当前最大允许的和决定往左还是往右走
话说稍微有点卡空间。。。(加了内存回收,然而理论上内存回收应该并不能改进最坏空间复杂度)
看了题解,发现只要暴力启发式合并/可并堆,合并完成后暴力删除最大值直到合法就行了。。。(因为每个点只会被删一次)
又想了想,只要暴力普通堆启发式合并就行了。。。。40行就行。。。
#pragma GCC optimize(3)//不开优化可能被卡常
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#define pb push_back
using namespace std;
typedef long long LL;
int n,m;
vector<int> ch[];
int c[],l[],fa[];
LL sum[];
priority_queue<int> q[];
LL ans;
void dfs(int u)
{
int i,v;
q[u].push(c[u]);sum[u]+=c[u];
for(i=;i<ch[u].size();i++)
{
v=ch[u][i];
dfs(v);
if(q[v].size()>q[u].size()) swap(q[u],q[v]);
while(!q[v].empty()) q[u].push(q[v].top()),q[v].pop();
sum[u]+=sum[v];
}
while(sum[u]>m) sum[u]-=q[u].top(),q[u].pop();
ans=max(ans,l[u]*LL(q[u].size()));
}
int main()
{
int i,a;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
{
scanf("%d%d%d",&a,&c[i],&l[i]);
fa[i]=a;ch[a].pb(i);
}
dfs();
printf("%lld",ans);
return ;
}
空间因为pq里面用了vector之类的好像会被卡。。。可以改一下
#pragma GCC optimize(3)//不开优化可能被卡常
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#define pb push_back
using namespace std;
typedef long long LL;
int n,m;
vector<int> ch[];
int c[],l[],fa[];
LL sum[];
priority_queue<int> *q[];
LL ans;
void dfs(int u)
{
int i,v;q[u]=new priority_queue<int>();
q[u]->push(c[u]);sum[u]+=c[u];
for(i=;i<ch[u].size();i++)
{
v=ch[u][i];
dfs(v);
if(q[v]->size()>q[u]->size()) swap(q[u],q[v]);
while(!q[v]->empty()) q[u]->push(q[v]->top()),q[v]->pop();
sum[u]+=sum[v];delete q[v];
}
while(sum[u]>m) sum[u]-=q[u]->top(),q[u]->pop();
ans=max(ans,l[u]*LL(q[u]->size()));
}
int main()
{
int i,a;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
{
scanf("%d%d%d",&a,&c[i],&l[i]);
fa[i]=a;ch[a].pb(i);
}
dfs();
printf("%lld",ans);
return ;
}
错误记录:答案没有开longlong所以无限WA
#include<cstdio>
#include<algorithm>
#include<vector>
#define pb push_back
using namespace std;
typedef long long LL;
namespace S
{
#define mid (l+((r-l)>>1))
#define N 3000000
int dat[N],lc[N],rc[N];LL sum[N];
int L;
int st[N+],top;
void init()
{
int i;
for(i=;i<N;i++) st[++top]=i;
}
int getnode()
{
int t=st[top--];dat[t]=sum[t]=lc[t]=rc[t]=;
return t;
}
void delnode(int x) {st[++top]=x;}
void _addx(int l,int r,int &num)
{
if(!num) num=getnode();
if(l==r) {dat[num]++;sum[num]+=l;return;}
if(L<=mid) _addx(l,mid,lc[num]);
else _addx(mid+,r,rc[num]);
dat[num]=dat[lc[num]]+dat[rc[num]];
sum[num]=sum[lc[num]]+sum[rc[num]];
}
void addx(int p,int &num)
{
L=p;_addx(,1e9,num);
}
int merge(int a,int b)
{
if(!a||!b) return a+b;
lc[a]=merge(lc[a],lc[b]);
rc[a]=merge(rc[a],rc[b]);
dat[a]+=dat[b];
sum[a]+=sum[b];
delnode(b);
return a;
}
int find(int l,int r,int num,LL msum)
{
if(l==r) return msum/l;
if(sum[lc[num]]>=msum) return find(l,mid,lc[num],msum);
else return find(mid+,r,rc[num],msum-sum[lc[num]])+dat[lc[num]];
}
#undef mid
}
vector<int> ch[];
int n,m;
int c[],l[],fa[];
int rt[];LL ans;
void dfs(int u)
{
S::addx(c[u],rt[u]);
for(int i=,v;i<ch[u].size();i++)
{
v=ch[u][i];
dfs(v);
rt[u]=S::merge(rt[u],rt[v]);
}
ans=max(ans,LL(l[u])*S::find(,1e9,rt[u],m));
}
int main()
{
int i,a;S::init();
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)
{
scanf("%d%d%d",&a,&c[i],&l[i]);
fa[i]=a;ch[a].pb(i);
}
dfs();
printf("%lld",ans);
return ;
}
[APIO2012]派遣 洛谷P1552 bzoj2809 codevs1763的更多相关文章
- 洛谷P1552 [APIO2012] 派遣 [左偏树,树形DP]
题目传送门 忍者 Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都 ...
- 2018.07.31洛谷P1552 [APIO2012]派遣(可并堆)
传送门 貌似是个可并堆的模板题,笔者懒得写左偏堆了,直接随机堆水过.实际上这题就是维护一个可合并的大根堆一直从叶子合并到根,如果堆中所有数的和超过了上限就一直弹直到所有数的和不超过上限为止,最后对于当 ...
- [洛谷P1552][APIO2012]派遣
题目大意:有一棵$n$个点的树,和一个费用$m$,每个点有一个费用和价值,请选一个点,再从它的子树中选取若干个点,使得那个点的价值乘上选的点的个数最大,要求选的点费用总和小于等于$m$ 题解:树形$d ...
- 洛谷P1552 [APIO2012]派遣(左偏树)
传送门 做这题的时候现学了一波左偏树2333(好吧其实是当初打完板子就给忘了) 不难发现肯定是选子树里权值最小的点且选得越多越好 但如果在每一个点维护一个小根堆,我们得一直找知道权值大于m为止,时间会 ...
- [洛谷P1552] [APIO2012]派遣(左偏树)
这道题是我做的左偏树的入门题,奈何还是看了zsy大佬的题解才能过,唉,我太弱了. 左偏树总结 Part 1 理解题目 很显然,通过管理关系的不断连边,最后连出来的肯定是一棵树,那么不难得出,当一个忍者 ...
- 题解 洛谷 P1552 【[APIO2012]派遣】
根据题意,我们不难发现忍者之间的关系是树形结构. 发现答案的统计只是在该节点的子树中,因此我们考虑通过树形\(DP\)来解决问题. 从叶子节点开始,从下往上考虑,因为一个节点的最优答案只与他的领导力和 ...
- 洛谷 - P1552 - 派遣 - 左偏树 - 并查集
首先把这个树建出来,然后每一次操作,只能选中一棵子树.对于树根,他的领导力水平是确定的,然后他更新答案的情况就是把他子树内薪水最少的若干个弄出来. 问题在于怎么知道一棵子树内薪水最少的若干个分别是谁. ...
- 洛谷 [P1552] 派遣
树型DP + 可并堆 非常清楚的想到是树型DP, 但是如何维护最小值, 于是就去新学了可并堆 #include <iostream> #include <cstring> #i ...
- 洛谷1552 [APIO2012]派遣
洛谷1552 [APIO2012]派遣 原题链接 题解 luogu上被刷到了省选/NOI- ...不至于吧 这题似乎有很多办法乱搞? 对于一个点,如果他当管理者,那选的肯定是他子树中薪水最少的k个,而 ...
随机推荐
- 将MySQL服务绑定到固定的IP地址上
近期将在线服务迁移到了阿里云. 阿里云提供了云盾,安全上确实比其他的云服务有了很大的提高,遗憾的是,没有防火墙,还是需要自己设置.阿里云的虚拟机跑在XEN上,直接使用YUM安装iptables ...
- 图像处理之 opencv 学习---opencv 中的常用算法
http://blog.csdn.net/lindazhou2005/article/details/1534234 文中有提到鲁棒性 http://blog.csdn.net/chary8088/a ...
- 键盘HOOK显示按键信息
GetKeyNameText(MapVirtualKey(iKeyValue,0)<<16));//iKeyValue 的值为 VK_ESCAPE 等 LRESULT CALLBACK L ...
- lc.exe 已退出 代码为 -1
地址:http://jingyan.baidu.com/article/91f5db1bd0ace31c7f05e321.html
- 微信小程序template使用
当您的项目需要多次使用同一个布局和样式的时候,您就可以考虑使用template(模板)来减少冗余代码. 使用方式: 1.新建一个template文件夹来存放您的通用模板: 2.在文件夹里面新建一个wx ...
- 超全!整理常用的iOS第三方资源(转)
超全!整理常用的iOS第三方资源 一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:hud提示框 地 ...
- bzoj4664: Count
是bzoj4498: 魔法的碰撞的哥哥题,我只写了一种 不一样的地方在于贡献有负数,第三维要保存的不能仅仅是0~L,这样空间会炸裂 考虑如何把贡献变成正的 假如要求最优解,那么一定是按顺序排,混乱度为 ...
- kafka条件查询excel拼接
1 SELECT COUNT(*) FROM wiseweb_crawler_metasearch_page20171214 WHERE (content like '%内蒙古%'or content ...
- SPOJ:Easy Factorials(占位)
Finding factorials are easy but they become large quickly that is why Lucky hate factorials. Today h ...
- BZOJ_1264_[AHOI2006]基因匹配Match_树状数组
BZOJ_1264_[AHOI2006]基因匹配Match_树状数组 Description 基因匹配(match) 卡卡昨天晚上做梦梦见他和可可来到了另外一个星球,这个星球上生物的DNA序列由无数种 ...