E. Photoshoot for Gorillas
题意
给定一个整数 \(T\),代表共有\(T\)组测试用例,对于每组测试用例:
给定四个整数 \(n,m,k和w(1 \leq n,m \leq 2 * 10^5, 1 \leq w \leq n * m \leq 2 * 10^5, 1 \leq k \leq min(n, m))\),随后输入 \(w\) 个整数 \(a_i\) 代表大猩猩的高度。
你需要从 \(n * m\) 的网格中,选出所有 \(k * k\) 的子网格,并且累计所有的子网格获取到的观赏价值。一个 \(k * k\) 的子网格获取到的观赏价值定义为:该网格内全部大猩猩的高度之和。
你要做的是将 \(w\) 只大猩猩按某个方式放入 \(n * m\) 的网格中,并且每个格子至多只能放置一只大猩猩,然后获取最大的观赏价值。
题解
\(\because\) 每个各自至多只能放置一只大猩猩
\(\therefore\) 将高度较高的大猩猩优先放置在所有子网格中出现频率最高的格子,可以获取到最大的观赏价值
对于格子 \((i, j)\),在所有的子网格中出现的频率为:$$freq = (min(k, (ll)n - i) + min(0LL, i + 1 - k)) * (min(k, (ll)m - j) + min(0LL, j + 1 - k))$$
那么,总体的代码思路就是对所有各自的频率排序,并对猩猩高度排序,从大到小依次配对即可。
参考代码
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);
using namespace std;
typedef long long ll;
constexpr int N = 2e5 + 7;
int T = 1, n, m, w;
ll k, ans;
int a1[N];
ll a2[N];
void solve() {
ans = 0;
cin >> n >> m >> k >> w;
for (int i = 0; i < w; ++ i) cin >> a1[i];
sort(a1, a1 + w, [](int &a, int &b) {
return a > b;
});
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < m; ++ j) {
a2[i * m + j] = (min(k, (ll)n - i) + min(0LL, i + 1 - k)) * (min(k, (ll)m - j) + min(0LL, j + 1 - k));
}
}
sort(a2, a2 + n * m, [](ll &a, ll &b) {
return a > b;
});
for (int i = 0; i < w; ++ i) {
ans += a1[i] * a2[i];
}
cout << ans << '\n';
}
int main() {
IOS
cin >> T;
while (T --) {
solve();
}
return 0;
}