给定长度为
n
n
n 的数组
a
a
a 和长度为
m
m
m 的数组
b
b
b ,以及一个整数
p
p
p 。
求
∑
i
=
0
n
−
1
∑
j
=
0
m
−
1
min
(
a
i
+
b
j
,
p
)
\sum\limits_{i=0}^{n-1}\sum\limits_{j=0}^{m-1} \min(a_i+b_j,p)
i=0∑n−1j=0∑m−1min(ai+bj,p)
对 a a a 和 b b b 从小到大排序,然后对 b b b 作前缀和。
考虑从前往后枚举每个
a
i
a_i
ai ,在
b
b
b 上二分找到最大的
b
j
b_j
bj 满足
a
i
+
b
j
<
p
a_i+b_j ai+bj<p
这部分又可以转化为双指针。
时间复杂度: O ( n log n ) O(n\log n) O(nlogn)
#include
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, p;
cin >> n >> m >> p;
vector<int> a(n), b(m);
for (int i = 0; i < n; ++i) cin >> a[i];
for (int i = 0; i < m; ++i) cin >> b[i];
sort(a.begin(), a.end());
sort(b.begin(), b.end());
vector<long long> preb(m);
for (int i = 0; i < m; ++i) {
preb[i] = b[i];
if (i > 0) preb[i] += preb[i - 1];
}
long long ans = 0;
for (int i = 0, j = m - 1; i < n; ++i) {
while (j >= 0 && a[i] + b[j] >= p) {
j -= 1;
}
// a[i] + b[j + 1] >= p
if (j == -1) {
ans += 1ll * m * p;
} else {
ans += 1ll * (m - 1 - j) * p;
ans += 1ll * a[i] * (j + 1);
ans += preb[j];
}
}
cout << ans << "\n";
return 0;
}