1. 程式人生 > 遊戲 >《死亡之屋:重製版》還將登陸Stadia和更多平臺

《死亡之屋:重製版》還將登陸Stadia和更多平臺

目錄

題目傳送門

題目描述

題目描述

出題是一件痛苦的事情!

相同的題目看多了也會有審美疲勞,於是我捨棄了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!

好吧,題目是這樣的:給出一串數以及一個數字 CC,要求計算出所有 A - B = CAB=C 的數對的個數(不同位置的數字一樣的數對算不同的數對)。

輸入格式

輸入共兩行。

第一行,兩個整數 N, CN,C

第二行,NN 個整數,作為要求處理的那串數。

輸出格式

一行,表示該串數中包含的滿足 A - B = CAB=C 的數對的個數。

輸入輸出樣例

輸入 #1複製

4 1
1 1 2 3

輸出 #1複製

3

說明/提示

對於 75%75% 的資料,1 \leq N \leq 20001≤N≤2000。

對於 100%100% 的資料,1 \leq N \leq 2 \times 10^51≤N≤2×105。

保證所有輸入資料絕對值小於 2^{30}230,且 C \ge 1C≥1。

2017/4/29 新添資料兩組

演算法求解

分析

  • 首先對給的陣列a排序

  • 然後用b陣列記錄每個數字及其出現次數(也是按照數字大小排序的)

  • 遍歷每種數字,對每種數字x,自己的數量是num1,二分查詢b中有沒有 x + c這個數字,有的話返回其數量num2,沒有返回-1

  • 那麼如果存在x+c,且其數量為num2,則這兩種陣列成的數對數量為num1 * num2

程式碼

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef pair<int, int> PII;
typedef long long LL;
const int N = 200010;
int a[N];
vector<PII> b;
int n, c;
int find(int x)
{
	int l = 0, r = b.size();
	while(l < r)
	{
		int mid = (r + l) >> 1;
		if(b[mid].first >= x) r = mid;
		else					   l = mid+1;
	}
	if(b[l].first != x) return -1;
	else			    return b[l].second;
} 

int main()
{
	scanf("%d%d", &n, &c);
	for(int i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
	}
	
	sort(a, a + n);
	
	int cnt = 0;	
	for(int i = 0; i < n; i++)
	{
		
		if(i && a[i] != a[i-1])
		{
			b.push_back({a[i-1], cnt});
			cnt = 0;
		}
		cnt++;
	}
	b.push_back({a[n-1], cnt});
	
//	for(int i = 0; i < b.size(); i++)
//		printf("%d %d\n", b[i].first, b[i].second);

	LL res = 0;
	for(int i = 0; i < b.size(); i++)
	{
		int t1 = b[i].first;
		int num1 = b[i].second;
		
		int t2 = find(t1 + c);
		if(t2 != -1)
		{
			res += (LL)t2 * num1;
		}
	}
	cout << res;
	
	return 0;
}

時間複雜度

\(O(nlogn)\)

參考文章