问题描述
小C管理着一个会员数据库,她希望能够尽可能高效地存储会员信息。每个会员的存储成本可以表示为一个线段长度,而她拥有的存储空间由块容器组成。每个会员和每块容器的长度可以是或。
为了提高存储效率,如果会员的信息存储在容器的两端位置,其存储成本可以压缩为一半,即。但是,一个会员只能被压缩一次。目标是最大化能够存储的会员数量,并计算存储成本的总和。
测试样例
样例1:
输入:
n = 5 , m = 2 , a = [1, 2, 2, 1, 2] , b = [2, 1]
输出:4
样例2:
输入:
n = 4 , m = 3 , a = [2, 1, 1, 2] , b = [1, 2, 1]
输出:4
样例3:
输入:
n = 6 , m = 2 , a = [2, 1, 1, 2, 1, 2] , b = [2, 2]
输出:5
注记
这道题没有表达清楚solution返回的数值的含义。实际上,solution返回的数值表示最多能够存储多少位会员的信息。
分析
问题的目标是 最大化 存储的会员数量 。每个会员的长度可以是或; 而任何会员可用的容器都是相同的,亦即总的存储容量与会员类型无关。因为总的存储容量是确定的, 所以存储的每个会员的长度越小,存储的会员数量就越多。因此,无论如何,我们应当优先存储长度为的会员;在长度为的会员都已经被存储、并且还有剩余容器的情况下,才考虑存储长度为的会员。
如何存储长度为1的会员
- 长度为容器,在容器两端使用压缩技术,得,即
- 能存储2位存储长度为1的会员。
- 1单位存储空间存储了2位用户。
- 长度为容器,在容器两端使用压缩技术,得,即
- 能存储3位存储长度为1的会员。
- 2单位存储空间存储了3位用户,亦即平均1单位存储空间存储了1.5位用户。
注意到,虽然相比单个长度为容器,单个长度为容器能够存储更多用户, 但是就单位空间能够存储的用户数目而言,有, 亦即长度为容器能够存储更多用户,是更好的选择。 (另一种理解方式:给定总存储空间为2,两个长度为容器能够存储4位用户,而 一个长度为容器只能存储3位用户。)
另外,在存储完长度为的会员时,如果容器有剩余空间,那么应该考虑将其用于 存储长度为的会员。因为、、 、。
如何存储长度为2的会员
可以类比上文的思路。
题解
#include <algorithm>
#include <vector>
using namespace std;
int solution(const int n, const int m, const vector<int>& a, const vector<int>& b)
{
int n_a1 = count(a.begin(), a.end(), 1), n_a2 = n - n_a1;
int n_b1 = count(b.begin(), b.end(), 1), n_b2 = m - n_b1;
int ans = 0, n_stores;
while (n_a1)
if (n_b1) {
n_stores = min(2, n_a1);
n_a1 -= n_stores;
ans += n_stores;
--n_b1;
} else if (n_b2) {
n_stores = min(3, n_a1);
if (n_stores == 1 && n_a2) {
--n_a2;
++ans;
}
n_a1 -= n_stores;
ans += n_stores;
--n_b2;
} else
break;
while (n_a2)
if (n_b1) {
--n_b1;
--n_a2;
++ans;
} else if (n_b2) {
n_stores = min(2, n_a2);
n_a2 -= n_stores;
ans += n_stores;
--n_b2;
} else
break;
return ans;
}