遞增三元組 暴力+動態規劃【藍橋杯真題】(c++實現)

上文鏈接:乘積尾零 因式分解【藍橋杯真題】(c++實現)


遞增三元組

給定三個整數數組

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

我的思路

  1. 由題中結果滿足Ai<Bj<Ck,可以通過查找數組 A 中小於 Bj 的最大值 i 和查找數組C中大於Bj的最小值k,查找到所有的i、k,則i * k 的積數和就爲三元組的個數,在查找過程中可以通過記錄i、j、k的位置做到簡化查找的步驟、通過處理頭部和尾部數據也可以簡化查找步驟,詳情看算法。
  2. 該題用暴力枚舉方法只能滿足30%的數據得不到滿分(對於100%的數據:(1053已經超出了一秒的運行時間,詳情查看1S的時間複雜度),因此需要採取查找歸納的方法簡化運算步驟。通過1中所述過程可以將語句執行次數減少到(1031 ,對於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;
}

下文鏈接:螺旋折線 一分鐘解決 【藍橋杯真題】(c++實現)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章