在某个游戏里,玩家可以给自己的角色穿上各种装备,每件装备都有自己的品质和属性。角色的属性可以通过穿戴的装备进行累加得到。
游戏中有 n n n 种装备,编号从1到 n n n,每件装备有一个品质 q i q_i qi 和三个属性值 a i a_i ai、 b i b_i bi 和 c i c_i ci。一件装备的属性可以简单地看做是其品质 q i q_i qi 与三个属性 a i a_i ai、 b i b_i bi 与 c i c_i ci 的乘积,即 p i = q i × a i × b i × c i p_i=q_i\times a_i\times b_i\times c_i pi=qi×ai×bi×ci。
一位玩家的角色已经穿戴了 m m m 件装备,其中第 i i i 件装备的编号为 p i p_i pi。角色的属性值可以分别表示为 A = ∑ i = 1 m a i A=\sum_{i=1}^m a_i A=∑i=1mai、 B = ∑ i = 1 m b i B=\sum_{i=1}^m b_i B=∑i=1mbi 以及 C = ∑ i = 1 m c i C=\sum_{i=1}^m c_i C=∑i=1mci。
现在,角色想要升级,需要找到一个品质值 Q Q Q 最小的装备进行替换,即找到编号 j j j 使得 q j < Q q_j
qj<Q且 p j > a j × b j × c j p_j>a_j\times b_j\times c_j pj>aj×bj×cj。如果存在多个符合要求的装备,那么应该选择编号最小的一个进行替换。
请你编写程序,求出符合要求的装备编号 j j j。
第一行两个整数 n n n 和 m m m,分别表示装备总数和玩家装备数。
接下来 n n n 行,每行描述一个装备。其中第 i i i 行包含四个整数 q i q_i qi、 a i a_i ai、 b i b_i bi 和 c i c_i ci,分别表示第 i i i 件装备的品质和三个属性值。
接下来 m m m 行,每行描述一件已经穿戴的装备。其中第 i i i 行包含一个整数 p i p_i pi,表示该装备的编号。
输出一个整数,表示符合要求的装备编号 j j j。如果不存在任何一件符合要求的装备,输出-1。
5 2 2 1 2 3 3 1 1 1 1 2 4 5 4 6 7 1 5 1 1 2 2 4
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
3
- 1
对于50%的评测用例, 1 ≤ n ≤ 100 1\leq n\leq 100 1≤n≤100, 1 ≤ m ≤ 50 1\leq m\leq 50 1≤m≤50。
对于100%的评测用例, 1 ≤ n ≤ 1 0 6 1\leq n\leq10^6 1≤n≤106, 1 ≤ m ≤ 1 0 5 1\leq m\leq 10^5 1≤m≤105, 1 ≤ q i ≤ 1 0 4 1\leq q_i\leq 10^4 1≤qi≤104, 1 ≤ a i , b i , c i ≤ 100 1\leq a_i,b_i,c_i\leq 100 1≤ai,bi,ci≤100, 1 ≤ p i ≤ 1 0 9 1\leq p_i\leq 10^9 1≤pi≤109。
对于50%的数据,可以直接暴力枚举符合条件的装备,然后选择品质最小的一个。时间复杂度为 O ( n m ) O(nm) O(nm)。
对于100%的数据,可以使用哈希表维护已经穿戴的装备编号,然后对于每个品质小于当前穿戴装备品质的装备,计算其属性值,如果符合要求则更新答案。同时,可以使用前缀和优化存储和计算属性值。时间复杂度为 O ( n ) O(n) O(n)。
题目来源:CSP-J 2020年模拟赛试题
首先,需要读懂题目并理解其中的问题:通过一种数据结构算法,找到符合要求的一件装备,从而求得其编号。在本题中,找到符合要求的装备需要满足两个条件:品质 q j q_j qj 小于指定值 Q Q Q,同时其属性 p j p_j pj 大于 a j × b j × c j a_j \times b_j \times c_j aj×bj×cj。其中, p j = q j × a j × b j × c j p_j=q_j\times a_j \times b_j \times c_j pj=qj×aj×bj×cj。
对于这道题目,最直接想到的方法是遍历所有可能的装备,找到符合要求的装备。但是这样的时间复杂度是 O ( n m ) O(nm) O(nm),即使 n n n 和 m m m 比较小也会超时。因此我们需要更加高效的算法解决此问题。
在本题中,我们可以通过哈希表存储已经穿戴的装备编号,然后对于每个品质小于当前穿戴装备品质的装备,计算其属性值,如果符合要求则更新答案。同时,可以使用前缀和优化存储和计算属性值。由于哈希表的查找时间是常数级别的,因此时间复杂度是 O ( n ) O(n) O(n),可以通过此题。
在确定好算法之后,我们就可以实现代码来解决本题。需要注意以下几点:
#include
using namespace std;
int main()
{
// 读入数据
int n, m, Q;
cin >> n >> m >> Q;
int q[m], a[m], b[m], c[m];
for (int i = 0; i < m; i++)
{
cin >> q[i] >> a[i] >> b[i] >> c[i];
}
// 处理数据
int ans = -1;
int has_worn[m+1] = {0}; // 哈希表记录已穿戴的装备
for (int i = 1; i <= n; i++)
{
int qq, aa, bb, cc;
cin >> qq >> aa >> bb >> cc;
int p = qq * aa * bb * cc; // 计算当前装备的属性值
for (int j = 0; j < m; j++)
{
if (q[j] < qq && !has_worn[j+1] && p > a[j] * b[j] * c[j]) {
ans = j + 1;
a[j] = b[j] = c[j] = 0; // 将已穿戴的装备清空
}
}
// 更新已穿戴的装备编号
if (qq <= Q)
{
has_worn[ans] = 1;
}
}
// 输出答案
cout << ans;
return 0;
}