[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个,而 ...
随机推荐
- LeetCode(21)题解:Merge Two Sorted Lists
https://leetcode.com/problems/merge-two-sorted-lists/ Merge two sorted linked lists and return it as ...
- SpringBoot项目 部署到服务器的tomcat下
把spring-boot项目按照平常的web项目一样发布到tomcat容器下 一.修改pom文件 修改打包方式 修改或增加maven插件 注意: 二.移除嵌入式tomcat插件 三.添加servlet ...
- inheritance super overrides printMethod in Superclass override重写父方法
Core Java Web Page http://horstmann.com/corejava.html [ inheritance ] package v1ch05.inheritance; im ...
- CodeForces 24D Broken robot(期望+高斯消元)
CodeForces 24D Broken robot 大致题意:你有一个n行m列的矩形板,有一个机器人在开始在第i行第j列,它每一步会随机从可以选择的方案里任选一个(向下走一格,向左走一格,向右走一 ...
- 您可能试图从server上的安全浏览器訪问此站点。请启用脚本然后又一次载入此页。
您可能试图从server上的安全浏览器訪问此站点.请启用脚本然后又一次载入此页. 我使用域Admin组的账户登入SharePoint2010的server,打开SharePoint首页 ...
- vmware Ubuntu忘记登录密码
VMware Workstation 上的Ubuntu 11.10 登录时,用户密码忘记了,以下是我对此问题解决的方法: 1)重新启动Ubtuntu 16 系统,同时长时间按住(或连续点击)esc键进 ...
- timestamp 转 date 处理后再转timestamp
package com.jmu.ccjoin.service.impl; import java.sql.Timestamp;import java.util.Calendar;import java ...
- POJ1077 Eight —— 正向BFS
主页面:http://www.cnblogs.com/DOLFAMINGO/p/7538588.html 代码一:以数组充当队列,利用结构体中的pre追溯上一个状态在数组(队列)中的下标: #incl ...
- DGA聚类 使用DBScan
features = sc.parallelize(data_group[idx]).map(lambda x: (x.host_ip+'^'+x.domain, 1)).reduceByKey(op ...
- HDU 1711(KMP)字符串匹配
链接 HDU 1711 Number Sequence KMP 算法 我以自己理解写的,写的不对,不明白的地方海王子出来,一起共同学习: 字符串匹配 就是KMP,一般思想,用一个for循环找开头 ...