枚举b[i]数组,在a[]数组中找有多少个数比b[i]小,在c[]数组中找有多少个数比b[i]大
然后两个数相乘
这个寻找的过程可以用两种方法实现
二分和前缀和
二分法
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[4][N];
int n;
int main()
{
cin >> n;
for (int i = 1; i <= 3; i++) {
for (int j = 0; j < n; j++) {
cin >> a[i][j];
}
}
sort(a[1], a[1] + n);
sort(a[3], a[3] + n);
// for(int i=1;i<=n;i++)
// cout<<a[1][i]<<' ';
// cout<<endl;
// for(int i=1;i<=n;i++)
// cout<<a[2][i]<<' ';
// cout<<endl;
long long ans = 0;
for (int i = 0; i < n; i++) {
int num1, num2;
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r + 1 >> 1;
if (a[1][mid] < a[2][i]) {
l = mid;
}
else r = mid - 1;
}
num1 = l;
if (a[1][l] >= a[2][i])
l = -1;
num1 = l;
l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (a[3][mid] > a[2][i]) {
r = mid;
}
else l = mid + 1;
}
num2 = l;
if (a[3][num2] <= a[2][i]) {
num2 = n;
}
//cout<<num1<<' '<<num2<<endl;
ans += (long long)(num1 + 1) * (n - num2);
//cout<<ans<<endl;
}
cout << ans << endl;
//system("PAUSE");
return 0;
}
前缀和法
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N], b[N], c[N];
int as[N], cs[N], cnt[N], s[N];
int n;
int main() {
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
a[i]++;
}
for (int i = 0; i < n; i++) {
cin >> b[i];
b[i]++;
}
for (int i = 0; i < n; i++) {
cin >> c[i];
c[i] ++;
}
for (int i = 0; i < n; i++) {
cnt[a[i]]++;
}
for (int i = 1; i < N; i++) {
s[i] = s[i - 1] + cnt[i];
}
for (int i = 0; i < n; i++) {
as[i] = s[b[i]-1];
}
memset(cnt, 0, sizeof(cnt));
memset(s, 0, sizeof(s));
for (int i = 0; i < n; i++) {
cnt[c[i]]++;
}
for (int i = 1; i < N; i++) {
s[i] = s[i - 1] + cnt[i];
}
for (int i = 0; i < n; i++) {
cs[i] = s[N - 1] - s[b[i]];
}
long long ans = 0;
for (int i = 0; i < n; i++) {
ans += (long long)as[i] * cs[i];
}
cout << ans << endl;
return 0;
}
对于前缀和求发为什么每个读入的要自加一啊
这里都要+1是防止数组越界,因为后续有下标-1的运算,如果数组中有数为0的话就会越界,比如:
这行代码 如果b[i] = 0时,那下标就会为-1,导致越界,我们在初始化时将数据全部+1就可以解决这个问题
谢谢dalao,我懂了
请问前缀和方法里的for (int i = 1; i < N; i++) {
s[i] = s[i - 1] + cnt[i]; i等于N的话为什么就错了呢?
下标问题吧