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的更多相关文章

  1. 洛谷P1552 [APIO2012] 派遣 [左偏树,树形DP]

    题目传送门 忍者 Description 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都 ...

  2. 2018.07.31洛谷P1552 [APIO2012]派遣(可并堆)

    传送门 貌似是个可并堆的模板题,笔者懒得写左偏堆了,直接随机堆水过.实际上这题就是维护一个可合并的大根堆一直从叶子合并到根,如果堆中所有数的和超过了上限就一直弹直到所有数的和不超过上限为止,最后对于当 ...

  3. [洛谷P1552][APIO2012]派遣

    题目大意:有一棵$n$个点的树,和一个费用$m$,每个点有一个费用和价值,请选一个点,再从它的子树中选取若干个点,使得那个点的价值乘上选的点的个数最大,要求选的点费用总和小于等于$m$ 题解:树形$d ...

  4. 洛谷P1552 [APIO2012]派遣(左偏树)

    传送门 做这题的时候现学了一波左偏树2333(好吧其实是当初打完板子就给忘了) 不难发现肯定是选子树里权值最小的点且选得越多越好 但如果在每一个点维护一个小根堆,我们得一直找知道权值大于m为止,时间会 ...

  5. [洛谷P1552] [APIO2012]派遣(左偏树)

    这道题是我做的左偏树的入门题,奈何还是看了zsy大佬的题解才能过,唉,我太弱了. 左偏树总结 Part 1 理解题目 很显然,通过管理关系的不断连边,最后连出来的肯定是一棵树,那么不难得出,当一个忍者 ...

  6. 题解 洛谷 P1552 【[APIO2012]派遣】

    根据题意,我们不难发现忍者之间的关系是树形结构. 发现答案的统计只是在该节点的子树中,因此我们考虑通过树形\(DP\)来解决问题. 从叶子节点开始,从下往上考虑,因为一个节点的最优答案只与他的领导力和 ...

  7. 洛谷 - P1552 - 派遣 - 左偏树 - 并查集

    首先把这个树建出来,然后每一次操作,只能选中一棵子树.对于树根,他的领导力水平是确定的,然后他更新答案的情况就是把他子树内薪水最少的若干个弄出来. 问题在于怎么知道一棵子树内薪水最少的若干个分别是谁. ...

  8. 洛谷 [P1552] 派遣

    树型DP + 可并堆 非常清楚的想到是树型DP, 但是如何维护最小值, 于是就去新学了可并堆 #include <iostream> #include <cstring> #i ...

  9. 洛谷1552 [APIO2012]派遣

    洛谷1552 [APIO2012]派遣 原题链接 题解 luogu上被刷到了省选/NOI- ...不至于吧 这题似乎有很多办法乱搞? 对于一个点,如果他当管理者,那选的肯定是他子树中薪水最少的k个,而 ...

随机推荐

  1. MySQL中给自定义的字段查询结果添加排名的方法

    我正在用 MySQL 客户端的时候,突然想到如果可以给查询结果添加排名该多好啊,然后就找到了一个简单的解决办法. 下面是一个示例表的数据:  然后我们要根据 Roll_No 字段进行排序并给出排名,我 ...

  2. 解压Zip

    import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import ja ...

  3. sublime 中配置 python 运行

    运行是按快捷键 ”ctrl + B“ Preferences->Browse Packages->Python->Python.sublime-build 编辑这个文件.   修改成 ...

  4. WebService:JAX-WS实现WebService

    WebService和Java核心技术中的RMI一样用于实现异构平台上的应用程序之间数据的交互,唯一不同的是这样的技术屏蔽了语言之间的差异.这也是其大行其道的原因. 实现WebService的技术多种 ...

  5. HDU 6073 Matching In Multiplication dfs遍历环 + 拓扑

    Matching In Multiplication Problem DescriptionIn the mathematical discipline of graph theory, a bipa ...

  6. C语言中的声明与定义的差别

    1.对于以下的声明语句 int a;        假设其位置出如今全部的函数体之外,那么它就被称为外部对象a的定义.这个语句说明了a是一个外部整型变量,同一时候为a分配了存储空间.由于外部对象a并没 ...

  7. dedecms列表页如何调用栏目关键词和描述

    问:dedecms列表页如何调用栏目关键词和描述 答:有人问起dedecms列表页如何调用栏目关键词和描述.解答如下: 自己实验了下总结方法如下:(以下方法使用于栏目封面和列表和内容页,其他的地方没有 ...

  8. poj 2771 Guardian of Decency 解题报告

    题目链接:http://poj.org/problem?id=2771 题目意思:有一个保守的老师要带他的学生来一次短途旅行,但是他又害怕有些人会变成情侣关系,于是就想出了一个方法: 1.身高差距   ...

  9. Android多国语言文件夹汇总

    Arabic, Egypt (ar-rEG) —————————–阿拉伯语,埃及 Arabic, Israel (ar-rIL) ——————————-阿拉伯语,以色列 Bulgarian, Bulg ...

  10. RecyclerView 局部刷新(获取viewHolder 去刷新)

    RecyclerView.ViewHolder viewHolder = mRecyclerView.findViewHolderForAdapterPosition(i); if (viewHold ...