遞增三元組
給定三個整數數組
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。
對於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
我的思路
- 由題中結果滿足Ai<Bj<Ck,可以通過查找數組 A 中小於 Bj 的最大值 i 和查找數組C中大於Bj的最小值k,查找到所有的i、k,則i * k 的積數和就爲三元組的個數,在查找過程中可以通過記錄i、j、k的位置做到簡化查找的步驟、通過處理頭部和尾部數據也可以簡化查找步驟,詳情看算法。
- 該題用暴力枚舉方法只能滿足30%的數據得不到滿分(對於100%的數據:(105)3已經超出了一秒的運行時間,詳情查看1S的時間複雜度),因此需要採取查找歸納的方法簡化運算步驟。通過1中所述過程可以將語句執行次數減少到(103)1 ,對於100%的數據大致也能完成而不會超時。
算法展示
#include <iostream>
using namespace std;
#include <algorithm>
int main()
{
int N,A[100001],B[100001],C[100001];
//輸入數據
cin>>N;
for(int i = 1;i<=N;i++)
{
cin>>A[i];
}
for(int i = 1;i<=N;i++)
{
cin>>B[i];
}
for(int i = 1;i<=N;i++)
{
cin>>C[i];
}
//排序
sort(A+1,A+N);
sort(B+1,B+N);
sort(C+1,C+N);
//初始化i,j,k
int i,j,k;
i = j = k =1;
//查找結果
long long ans = 0;
while(j<=N)
{
while(i<N&&A[i]<B[j])i++;//查找比Bj小的i (A爲遞增數組)
while(k<N&&B[j]>C[k])k++;//查找比Bj大的k(C爲遞增數組)
ans+=(long long)(i*(N-k+1));//積數和運算
j++;
}
cout<<ans<<endl;
return 0;
}