题目
给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:
1.1 <= i, j, k <= N
2.Ai < Bj < Ck
【输入格式】
第一行包含一个整数N。
第二行包含N个整数A1, A2, … AN。
第三行包含N个整数B1, B2, … BN。
第四行包含N个整数C1, C2, … CN。
对于30%的数据,1 <= N <= 100
对于60%的数据,1 <= N <= 1000
对于100%的数据,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000
【输出格式】
一个整数表示答案
【样例输入】
3
1 1 1
2 2 2
3 3 3
【样例输出】
27
资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗 < 1000ms
解题思路
题目不难。可以用一个3行100001列的数组data记录每行数字出现的次数,如data[0][5]表示A中5出现的次数。再用一个3行100001列的数组S记录data的前缀和。最后遍历B中的每一个数 Bi,使用前缀和求出A中<Bi的数的总和和C中>Bi的数的总和, 再相乘加到ans里面。
注意由于最后答案可能很大,所以ans和S都要使用long long。(曾经S没有使用long long导致N=100000的样例没过~~)最后,代码复杂度为O(n)。
代码如下:
代码
#include<cstdio>
#include<iostream>
#include<cstdlib>
using namespace std;
const int MAX_M = 3;
const int MAX_N = 1e5+5;
typedef long long LL;
LL Data[MAX_M][MAX_N];
LL S[MAX_M][MAX_N];
int N;
int nbr;
LL ans=0;
void solve() {
scanf("%d", &N);
int i, j, k;
for(i=0; i<3; i++){
for(j=0; j<N; j++){
scanf("%d", &nbr);
Data[i][nbr]++;
}
}
S[0][0] = Data[0][0];
S[1][0] = Data[1][0];
S[2][0] = Data[2][0];
for(i=0; i<3; i++){
for(j=1; j<MAX_N; j++){
S[i][j] = S[i][j-1] + Data[i][j];
}
}
for(i=1; i<MAX_N-1; i++){
ans+=Data[1][i]*S[0][i-1]*(S[2][MAX_N-1]-S[2][i]);
}
printf("%lld\n", ans);
}
int main() {
solve();
return 0;
}