887 字
4 分钟
Table-With-Numbers

Table-with-Numbers#

题面#

Peter drew a table of size h×lh \times l, filled with zeros. We will number its rows from 11 to hh from top to bottom, and columns from 11 to ll from left to right. Ned came up with an array of numbers a1,a2,,ana_1, a_2, \ldots, a_n and wanted to modify the table.

Ned can choose 2kn2k \leq n numbers from his array and split them into kk pairs. After that, for each resulting pair x,yx, y, he takes the cell located in row xx and column yy, and adds 11 to the number in that cell. If such a cell does not exist, then this pair does nothing to the table.

Peter supported Ned’s initiative and asked him to maximize the sum of the numbers in the table. Help Ned understand what the maximum sum he can achieve is.

Input

Each test contains multiple test cases. The first line contains the number of test cases tt (1t5001 \le t \le 500). The description of the test cases follows.

The first line of each test case contains three integers nn, hh, and ll (2n1002 \le n \le 100, 1h,l10001 \le h, l \le 1000) — the size of the array, the height of the table, and the width of the table, respectively.

The second line of each test case contains nn numbers a1a_1, a2a_2, \ldots, ana_n (1ai10001 \le a_i \le 1000) — the array itself.

Output

For each test case, output the maximum possible sum of the numbers in the table.

思路#

先把题目理清楚:

  • 表格初始全是 00,每做一个有效配对 (x,y)(x,y)(满足 1xh, 1yl1\le x\le h,\ 1\le y\le l),表格总和就 +1+1
  • 所以题目本质是:最多能做出多少个有效配对

1. 按“可担任角色”分类#

一个数在配对里可能担任“行号”或“列号”

  • aiha_i \le h,它可以当行号
  • aila_i \le l,它可以当列号

据此分 4 类:

  1. bothaiha_i \le haila_i \le l(行列都能当)
  2. raiha_i \le hai>la_i > l(只能当行)
  3. cai>ha_i > haila_i \le l(只能当列)
  4. uai>ha_i > hai>la_i > l(行列都不能当)

记数量分别为 B,R,CB,R,C(第 4 类无需统计)

2. 哪些配对有效?#

一个配对要有效,必须“有行也有列”:

  • 有效:r+cboth+rboth+cboth+both
  • 无效:r+rc+c、以及任何含 u 的配对

因此,我们只要最大化上面 4 种有效配对的总数

3. 贪心构造(最优)#

第一步:先配 rc#

  • 能配多少配多少:x=min(R,C)x=\min(R,C)
  • 这一步每对都必定有效,且不会消耗 both 这种“万能资源”

更新:

  • 答案加 xx
  • RRx, CCxR\leftarrow R-x, \ C\leftarrow C-x

第二步:剩余单侧角色用 both 补齐#

第一步后,R,CR,C 至多只有一个还大于 00。这些剩余元素必须和 both 配才有效

  • 可补数量:y=min(B,R+C)y=\min(B, R+C)
  • 答案加 yy
  • BByB\leftarrow B-y

第三步:剩余 both 两两互配#

  • 每两枚 both 可以组成一对有效配对
  • 贡献 B/2\left\lfloor B/2\right\rfloor

最终答案:

extans=x+y+B2 ext{ans}=x+y+\left\lfloor\frac{B}{2}\right\rfloor
NOTE

验证贪心正确性

  • rc 彼此配对时,不需要 both,这是对资源最节省的做法
  • both 既能当行又能当列,是稀缺的“通用补位” 如果过早让 both 参与配对,会挤占后续补齐单侧角色的能力,不> 会更优
  • 当单侧角色补齐后,剩下只有 both,唯一有效用法就是 both + both

所以按上述顺序贪心,不会错过更优方案

代码#

#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, h, l;
cin >> n >> h >> l;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++) cin >> a[i];
long long both = 0, r = 0, c = 0;
for (int i = 1; i <= n; i ++) {
if (a[i] <= h && a[i] <= l) {
both ++;
} else if (a[i] <= h) {
r ++;
} else if (a[i] <= l) {
c ++;
}
}
long long ans = 0;
long long cross = min(r, c);
ans += cross;
r -= cross;
c -= cross;
long long b = min(both, r + c);
ans += b;
both -= b;
ans += both / 2;
cout << ans << '\n';
}
return 0;
}
Table-With-Numbers
https://github.com/posts/table-with-numbers/
作者
FZSGBall
发布于
2026-04-09
许可协议
CC BY-NC-SA 4.0