思路
每个单元格 (i,j) 的最终值为 max(r[i], c[j]),总和为所有 max(r[i], c[j]) 的累加。
对列数组 c 排序并计算前缀和,方便快速统计 “小于等于当前行值 r[i] 的列数” 和 “大于当前行值的列的总和”。
遍历每个行值 r[i],通过二分查找找到 c 中第一个大于 r[i] 的位置,从而拆分列数组为 “≤r [i]” 和 “>r [i]” 两部分,分别计算贡献。
#include <bits/stdc++.h>
using namespace std;
#define sc second
#define fr first
#define int long long
#define itn long long
#define vi vector<int>
#define vvi vector<vector<int>>
#define endl '\n'
// const int mod = 998244353;
// const int mod = 1e10 + 7;
int n, m, k, q, x, num, sum = 0, cnt = 0, l = 1, r = 1e10;
string s;
void _()
{
cin >> n >> m;
vi r(n);
for (int i = 0; i < n; ++i)
{
cin >> r[i];
}
vi c(m);
for (int i = 0; i < m; ++i)
{
cin >> c[i];
}
sort(c.begin(), c.end());
//这之前都是初始化和排序,不讲了awa
vector<int> q(m + 1, 0);
for (int i = 0; i < m; ++i)
{
q[i + 1] = q[i] + c[i];//"q"即前缀和的拼音首字母,记录前缀和
}
int tot = 0;
for (int i : r)//一行一行的找,一行一行的加
{
int pos = upper_bound(c.begin(), c.end(), i) - c.begin();//直接调用函数去找恰好比r[i]大的位置
tot += (i * pos + (q[m] - q[pos]));//看看这一行里,哪些是比r[i]小的,小的话就换成r[i]并且计入,否则就是c本身(此处用前缀和计算比r[i]大的部分的总和)
}
cout << tot << endl;
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int awa = 1;
// cin >> awa;
while (awa--)
{
_();
}
return 0;
}
喜欢的话请点个赞吧awa
(题外话:我看着这c嘎嘎的题解没有这就给补上了)

京公网安备 11010502036488号