NC17315 背包
题目
题目描述
Applese有 \(1\) 个容量为 \(v\) 的背包,有 \(n\) 个物品,每一个物品有一个价值 \(a_i\) ,以及一个大小 \(b_i\)
然后他对此提出了自己的疑问,如果我不要装的物品装的价值最大,只是一定需要装 \(m\) 个物品,要使得求出来的物品价值的中位数最大
Applese觉得这个题依然太菜,于是他把这个问题丢给了你
当物品数量为偶数时,中位数即中间两个物品的价值的平均值
输入描述
第一行三个数 \(v, n, m\) ,分别代表背包容量,物品数量以及需要取出的物品数量
接下来n行,每行两个数 \(a_i,b_i\) ,分别代表物品价值以及大小
\(n ≤ 1e5, 1 ≤ m ≤ n, a_i ≤ 1e9, v ≤ 1e9, b_i ≤ v\)
输出描述
仅一行,代表最大的中位数
示例1
输入
20 5 3
3 5
5 6
8 7
10 6
15 10
输出
8
题解
知识点:优先队列,贪心,二分。
由于要求的长为 \(m\) 的序列的中位数最大值,直接从 \(n\) 个数里枚举 \(m\) 个数会很困难。用dp解决的话,每种可能都要记录还要求一下中位数,也是不可行的。
但是因为是中位数,所以换一种角度,把每个数当作中位数,去匹配一组使其成为中位数的序列。这是很好处理的,只要比这个数小的数存在一定数量个,比这个数大的数存在一定数量个即可,然后从其中取得最小的一组序列重量值,因为我们不关心除了中位数的其他数的价值。
具体地说,我们先考虑 \(m\) 为奇数,那么一个数左右侧都需要有 \(\lfloor \frac{m}{2} \rfloor\) 个数,取他们重量最小值。因此为了使得枚举中位数更加方便,我们先从小到大排序价值,然后从左往右遍历维护一个长度为 \(\lfloor \frac{m}{2} \rfloor\) 的按重量的小顶堆,并在过程中维护动态前 \(\lfloor \frac{m}{2} \rfloor\) 小的和 \(s1[i]\) ,即可得到 \([1,i]\) 中重量前 \(\lfloor \frac{m}{2} \rfloor\) 小的和 。同理从右到左维护一个 \(s2[i]\) ,即 \([i,n]\) 中重量前 \(\lfloor \frac{m}{2} \rfloor\) 小的和。
之后我们对每个数进行判断 s1[i - 1] + a[i].b + s2[i + 1] <= v ,满足的即合法,那么就可以参与最大值的判断。
接下来考虑 \(m\) 为偶数,因为偶数序列中位数是中间两个数之和取下整,因此我们要考虑两个数,一个数维护左侧,一个数维护右侧。那先枚举左边的数,而另一个数因为只需要考虑右侧重量和,由于价值会从左往右递增,而最小重量和一定是递增的(假设一定满足中位数的右侧个数需求),那么会存在一个点使得右侧数字不能成为中位数,左侧数字可以成为中位数但比这个数小,即符合单调性可以二分求解。要注意的是前后缀最小重量和在偶数情况维护的是前 \(\lfloor \frac{m}{2} \rfloor - 1\) 小个。
时间复杂度 \(O(n\log n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int v, n, m;
struct node {
int a, b;
}a[100007];
ll s1[100007], s2[100007];
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> v >> n >> m;
for (int i = 1;i <= n;i++) cin >> a[i].a >> a[i].b;
sort(a + 1, a + n + 1, [&](node a, node b) {return a.a < b.a;});
priority_queue<int> pq;
for (int i = 1;i <= n;i++) {///k小前缀和,维护中位数左侧
s1[i] = s1[i - 1] + a[i].b;
pq.push(a[i].b);
if (pq.size() > m / 2 - !(m & 1)) {
s1[i] -= pq.top();
pq.pop();
}
}
while (!pq.empty()) pq.pop();
for (int i = n;i >= 1;i--) {///k小后缀和,维护中位数右侧
s2[i] = s2[i + 1] + a[i].b;
pq.push(a[i].b);
if (pq.size() > m / 2 - !(m & 1)) {
s2[i] -= pq.top();
pq.pop();
}
}
int ans = 0;
if (m & 1) {///奇数直接枚举中位数
for (int i = m / 2 + 1;i <= n - m / 2;i++)
if (s1[i - 1] + a[i].b + s2[i + 1] <= v)
ans = max(ans, a[i].a);
}
else {///偶数枚举一个之后,二分另一个
for (int i = m / 2;i <= n - m / 2;i++) {
if (s1[i - 1] + a[i].b + s2[i + 1] <= v) {///小优化
int l = i + 1, r = n - m / 2 + 1;
while (l <= r) {
int mid = l + r >> 1;
if (s1[i - 1] + a[i].b + a[mid].b + s2[mid + 1] <= v) l = mid + 1;
else r = mid - 1;
}
if (r > i)ans = max(ans, a[i].a + a[r].a >> 1);///不一定找得到
}
}
}
cout << ans << '\n';
return 0;
}
NC17315 背包的更多相关文章
- 【USACO 3.1】Stamps (完全背包)
题意:给你n种价值不同的邮票,最大的不超过10000元,一次最多贴k张,求1到多少都能被表示出来?n≤50,k≤200. 题解:dp[i]表示i元最少可以用几张邮票表示,那么对于价值a的邮票,可以推出 ...
- HDU 3535 AreYouBusy (混合背包)
题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...
- HDU2159 二维完全背包
FATE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- CF2.D 并查集+背包
D. Arpa's weak amphitheater and Mehrdad's valuable Hoses time limit per test 1 second memory limit p ...
- UVALive 4870 Roller Coaster --01背包
题意:过山车有n个区域,一个人有两个值F,D,在每个区域有两种选择: 1.睁眼: F += f[i], D += d[i] 2.闭眼: F = F , D -= K 问在D小于等于一定限度的时 ...
- 洛谷P1782 旅行商的背包[多重背包]
题目描述 小S坚信任何问题都可以在多项式时间内解决,于是他准备亲自去当一回旅行商.在出发之前,他购进了一些物品.这些物品共有n种,第i种体积为Vi,价值为Wi,共有Di件.他的背包体积是C.怎样装才能 ...
- POJ1717 Dominoes[背包DP]
Dominoes Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6731 Accepted: 2234 Descript ...
- HDU3466 Proud Merchants[背包DP 条件限制]
Proud Merchants Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) ...
- POJ1112 Team Them Up![二分图染色 补图 01背包]
Team Them Up! Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 7608 Accepted: 2041 S ...
- UVA - 11137 Ingenuous Cubrency[背包DP]
People in Cubeland use cubic coins. Not only the unit of currency iscalled a cube but also the coins ...
随机推荐
- SV 字符串类型
概述 常见使用方式 string b; string b=""; // 拼接字符串 string a = {"hi",b}; // 将字符串a赋值给[15:0] ...
- 05-Verilog基础语法_4
Verilog基础语法 Mixed Model(混合设计模型) System Tasks(系统任务,系统函数) 用随机数驱动验证 fd = $fopen("文件路径及文件名") / ...
- 【ArgParse】一个开源的入参解析库
项目地址:argtable3 本地验证: 编译构建 新增验证 // examples/skull.c #include "argtable3.h" int main(int arg ...
- 百度网盘(百度云)SVIP超级会员共享账号每日更新(2024.01.08)
一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...
- [转帖]Rocksdb的优劣及应用场景分析
研究Rocksdb已经有七个月的时间了,这期间阅读了它的大部分代码,对底层存储引擎进行了适配,同时也做了大量的测试.在正式研究之前由于对其在本地存储引擎这个江湖地位的膜拜,把它想象的很完美,深入摸 ...
- [转帖]以 PostgreSql 为例,说明生产级别数据库安装要考虑哪些问题?
https://xie.infoq.cn/article/487b467b952683e6dd27d9061 我让公司的小伙伴写一个生产级别的 PostgreSQL 的安装文档,结果他和我说:&quo ...
- HotSpare 9361Raid卡热备盘的设置过程
HotSpare 9361Raid卡热备盘的设置过程 摘要 公司最近一批服务器到位(去年生产) 插满24盘位的 960G 的SSD 的超融合服务器. (硬盘是镁光的 !-_-!) 想着Raid6虽然数 ...
- 【转帖】什么是RLHF
什么是RLHF? **字面翻译:**RLHF (Reinforcement Learning from Human Feedback) ,即以强化学习方式依据人类反馈优化语言模型. 强化学习从人类反馈 ...
- 我们开源了一个 Ant Design 的单元测试工具库
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 本文作者:佳岚 欢迎大家点一个小小的 Star ant-design ...
- elementui中el-checkbox 选中时的详细介绍
checkbox-group 把多个checkbox管理为一组(需要注意的坑) 很多时候我们需要会遇见这样的场景. 比如用户需要选择多个值. 这个时候我们需要把多个 checkbox 放置在check ...