【题解】Atcoder ARC#96 F-Sweet Alchemy
首先,我们发现每一个节点所选择的次数不好直接算,因为要求一个节点被选择的次数大于等于父亲被选择的次数,且又要小于等于父亲被选择的次数 \(+D\)。既然如此,考虑一棵差分的树,规定每一个节点被选择的次数为 \(x\),表示节点实际上被选择的次数是父亲被选择的次数 \(+x\)。显然,这个 \(x\) 是小于等于 \(D\) 的。分析这样我们发现,选择了一个节点实际上对应子树内的所有节点的选择次数均增加,所以我们重新定义选择一个节点的价值为子树内(含自身)节点的个数,而代价则是子树内所有代价的总和(含自身)。
问题转化为:在一棵树上有不超过 \(50\) 个节点,每个节点均有一个权值及一个代价,除\(1\) 号节点外每个节点选择的次数均不能超过 \(D\)。求在总代价不超过 \(x\) 的前提下,如何使权值最大化?
想到这里我就懵逼了。乍一看背包,然而代价的范围过大,根本不可能实现。突破口只有非常小的 \(n\) 的范围了。想了很久也不会,看题解。还是非常强的。
在最开始学背包的时候,会有一个错误的想法:对于权值为 \(v_{i}\),代价为 \(w_{i}\) 的若干物品,我们计算出它们的性价比,贪心的选择其中性价比高的部分物品。这样之所以是错的,是由于物品不能分割,这样会有空闲的地方出现但又不能塞入更好的物品了。于是我们考虑:在什么样的情况下可以直接用性价比高的物品代替性价比低的物品呢?
考虑两个物品 \(v_{i}, w_{i}\) 和 \(v_{j}, w_{j}\),其中 \(\frac{v_{i}}{w_{i}} > \frac{v_{j}}{w_{j}}\) 即 \(i\) 物品的性价比高于 \(j\)。如果我们选择了 \(v_{i}\) 个物品 \(j\) ,不如直接更换成 \(v_{j}\) 个物品 \(i\)。这样权值是相等的,都是 \(v_{i}*v_{j}\),但代价却更小:\(v_{j} * w_{i} < v_{i} * w_{j} \)。由此我们知道:在可以选择性价比更高的物品却没有选择的情况下,性价比低的物品最多选择 \(v_{i} - 1\) 个。而这个 \(v\) 的范围是很小的,所以我们可以对于每一种物品都从其中拿出 \(min(n, D)\) 件来进行多重背包,剩下的贪心即可。
- #include <bits/stdc++.h>
- using namespace std;
- #define maxn 55
- #define maxm 125005
- #define int long long
- #define INF 1e9 + 10
- int n, X, D, ans, cnt, dp[maxm];
- int w[maxn], val[maxn], pos[maxn];
- int tot, V[maxn * maxn], W[maxn * maxn];
- int read()
- {
- int x = , k = ;
- char c; c = getchar();
- while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
- while(c >= '' && c <= '') x = x * + c - '', c = getchar();
- return x * k;
- }
- struct edge
- {
- int cnp, to[maxn], last[maxn], head[maxn];
- edge() { cnp = ; }
- void add(int u, int v)
- { to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++; }
- }E1;
- void dfs(int u)
- {
- val[u] = ;
- for(int i = E1.head[u]; i; i = E1.last[i])
- {
- int v = E1.to[i];
- dfs(v);
- w[u] += w[v]; val[u] += val[v];
- }
- cnt += val[u] * n; pos[u] = u;
- }
- bool cmp(int x, int y) { return val[x] * w[y] > val[y] * w[x]; }
- void Get_min(int &x, int y) { x = x < y ? x : y; }
- signed main()
- {
- n = read(), X = read(), D = read();
- w[] = read();
- for(int i = ; i <= n; i ++)
- {
- w[i] = read(); int x = read();
- E1.add(x, i);
- }
- dfs();
- sort(pos + , pos + n + , cmp);
- int tmp = min(n, D);
- for(int i = ; i <= cnt; i ++) dp[i] = INF;
- for(int i = ; i <= n; i ++)
- {
- int len = , lim = tmp;
- while(lim >= len)
- {
- V[++ tot] = len * val[pos[i]];
- W[tot] = len * w[pos[i]];
- lim -= len, len <<= ;
- }
- if(lim) V[++ tot] = lim * val[pos[i]], W[tot] = lim * w[pos[i]];
- }
- for(int i = ; i <= tot; i ++)
- for(int j = cnt; ~j; j --)
- if(j >= V[i]) Get_min(dp[j], dp[j - V[i]] + W[i]); // k件物品
- int ans = ;
- for(int i = ; i <= cnt; i ++)
- {
- if(dp[i] > X) continue;
- int ret = i, left = X - dp[i];
- for(int j = ; j <= n; j ++)
- {
- int tem = pos[j], used = min(max(D - n, 0LL), left / w[tem]);
- if(tem == ) used = left / w[tem];
- left -= w[tem] * used;
- ret += val[tem] * used;
- }
- ans = max(ans, ret);
- }
- printf("%lld\n", ans);
- return ;
- }
【题解】Atcoder ARC#96 F-Sweet Alchemy的更多相关文章
- 【题解】 AtCoder ARC 076 F - Exhausted? (霍尔定理+线段树)
题面 题目大意: 给你\(m\)张椅子,排成一行,告诉你\(n\)个人,每个人可以坐的座位为\([1,l]\bigcup[r,m]\),为了让所有人坐下,问至少还要加多少张椅子. Solution: ...
- [题解] Atcoder ARC 142 D Deterministic Placing 结论,DP
题目 (可能有点长,但是请耐心看完,个人认为比官方题解好懂:P) 首先需要注意,对于任意节点i上的一个棋子,如果在一种走法中它走到了节点j,另一种走法中它走到了节点k,那么这两种走法进行完后,棋子占据 ...
- [题解] Atcoder ARC 142 E Pairing Wizards 最小割
题目 建图很妙,不会. 考虑每一对要求合法的巫师(x,y),他们两个的\(a\)必须都大于\(min(b_x,b_y)\).所以在输入的时候,如果\(a_x\)或者\(a_y\)小于\(min(b_x ...
- *AtCoder Regular Contest 096F - Sweet Alchemy
$n \leq 50$的树,每个点有权值,现要选点(可多次选一个点)使点数尽量多,如下限制:选的总权值不超过$C \leq 1e9$:$c_i$表示$i$选的次数,$p_i$表示$i$的父亲,那么$c ...
- [题解] Atcoder AGC 005 F Many Easy Problems NTT,组合数学
题目 观察当k固定时答案是什么.先假设每个节点对答案的贡献都是\(\binom{n}{k}\),然后再减掉某个点没有贡献的选点方案数.对于一个节点i,它没有贡献的方案数显然就是所有k个节点都选在i连出 ...
- [atcoder contest 010] F - Tree Game
[atcoder contest 010] F - Tree Game Time limit : 2sec / Memory limit : 256MB Score : 1600 points Pro ...
- Atcoder Regular Contest 096 D - Sweet Alchemy(贪心+多重背包)
洛谷题面传送门 & Atcoder 题面传送门 由于再过 1h 就是 NOI 笔试了所以题解写得会略有点简略. 考虑差分,记 \(b_i=c_i-c_{fa_i}\),那么根据题意有 \(b_ ...
- [题解] Atcoder Regular Contest ARC 147 A B C D E 题解
点我看题 A - Max Mod Min 非常诈骗.一开始以为要观察什么神奇的性质,后来发现直接模拟就行了.可以证明总操作次数是\(O(nlog a_i)\)的.具体就是,每次操作都会有一个数a被b取 ...
- 【题解】Atcoder ARC#90 F-Number of Digits
Atcoder刷不动的每日一题... 首先注意到一个事实:随着 \(l, r\) 的增大,\(f(r) - f(l)\) 会越来越小.考虑暴力处理出小数据的情况,我们可以发现对于左端点 \(f(l) ...
随机推荐
- Python学习总结 05 pandas
pandas官方网址 : http://pandas.pydata.org/ . pandas的安装比较复杂,如果想开箱即用,可以考虑下载WinPython.WinPython的官方地址是: htt ...
- 学习Key与Value的集合hashtable
你可以创建一个hashtable: 你可以使用foreach方法,把hashtable的key与value循环写出来: 在控制台屏幕输出: 如果只需把key输出: 如果只想把值循环输出: 测试输出结果 ...
- kafka学习2:kafka集群安装与配置
在前一篇:kafka学习1:kafka安装 中,我们安装了单机版的Kafka,而在实际应用中,不可能是单机版的应用,必定是以集群的方式出现.本篇介绍Kafka集群的安装过程: 一.准备工作 1.开通Z ...
- Luogu P2059 [JLOI2013]卡牌游戏
一道比较简单的概率DP 首先看到这种题目和数据范围,就要毫不犹豫地列DP方程: 我们令\(f_{i,j}\)表示还剩下i个人时编号为j的人的胜率,那么首先我们可以知道边界条件\(f_{1,1}=1\) ...
- 关于LCA
LCA:最近公共祖先 指在有根树中,找出某两个结点u和v最近的公共祖先 如图,5,7的最近公共祖先就是3 接下来,我们来了解如何求解LCA No.1 暴力 首先想到的肯定是暴力,我们搜索,从两个节点一 ...
- 基于uFUN开发板的心率计(一)DMA方式获取传感器数据
前言 从3月8号收到板子,到今天算起来,uFUN到手也有两周的时间了,最近利用下班后的时间,做了个心率计,从单片机程序到上位机开发,到现在为止完成的差不多了,实现很简单,uFUN开发板外加一个Puls ...
- 1kb的前端HTML模板解析引擎,不限于嵌套、循环、函数你能想到的解析方式
传送门:https://github.com/xiangyuecn/BuildHTML copy之前说点什么 html做点小功能(什么都没有),如果是要手动生成html这种操作,容易把代码搞得乱七八糟 ...
- 【教你玩转云计算】在阿里云一键安装快速部署Oracle11g
云计算时代提供了更方便可靠的IAAS,PAAS和SAAS平台.将已有或正在研发的项目迁移到云计算平台,和传统的服务器部署还是存在一些异同点. 本文手把手教你在阿里云平台快速的部署Oracle11g ...
- Jmeter(三十三)_JsonPath表达式提取响应
我们在用jmeter做接口测试的时候,有的时候会遇到一些复杂的json响应.比如多层list嵌套时的取值 一个简单的例子: $..Name:列出所有省份 $..Province[0].Name 提取P ...
- MRT与MRTS工具官宣退休,推荐使用HEG
今天错误的删除搞丢了之前下载的MRT与MRTS工具,浏览Modis官网下载时发现找不到了,后来在其官网上发现了这则通知,原来早已停止更新的MRT这次彻底退修了.通知原文如下~~~ The downlo ...