给定三个整数数组
A=[A1,A2,…AN],
B=[B1,B2,…BN],
C=[C1,C2,…CN],
请你统计有多少个三元组 (i,j,k) 满足:
1≤i,j,k≤N
Ai<Bj<Ck
输入格式
第一行包含一个整数 N。
第二行包含 N 个整数 A1,A2,…AN。
第三行包含 N 个整数 B1,B2,…BN。
第四行包含 N 个整数 C1,C2,…CN。
输出格式
一个整数表示答案。
数据范围
1≤N≤105,
0≤Ai,Bi,Ci≤105
输入样例:
3
1 1 1
2 2 2
3 3 3
输出样例:
27
三个数组,要满足的是Ai < Bj < Ck;如果先确定A中那个数,俺么后面的两个做选择的时候还是会受限制,所以我们先确定B中选择哪一个数,这样A和C相互是独立的,可以用乘法原理
我们开一个数组,每个位置存放的是(小于【A】/大于【C】)B[i]的有多少个;
然后遍历相乘就行了;
以数组A的过程举例,要找对于每一个B[i],有多少个是小于他的;
int as[N];as[i]是数组A中有多少个数小于b[i]
怎么计算as呢?
开一个cnt数组和s数组分别用来计数和计算前缀和;
遍历A数组,把数字存放在cnt数组相应的下标位置。cnt表示的就是下标数字有多少个;
然后对这个数组计算前缀和,为了要的到比这个数小的有多少个;
然后计算出as[i]
代码如下
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int a[N], b[N], c[N];
int as[N], cs[N];
int cnt[N], s[N];
int main()
{
int n;
scanf("%d", &n);
for(int i = 0; i < n; i ++ ) scanf("%d", &a[i]), a[i] ++;
for(int i = 0; i < n; i ++ ) scanf("%d", &b[i]), b[i] ++;
for(int i = 0; i < n; i ++ ) scanf("%d", &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];
//因为这里是从1开始计算的前缀和,而数组A和C输入可能是有0的
//所以在输入的时候给他都加1,这样就保证了cnt数组的0位置没有意义。
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;
}