優必選釋出仿人服務機器人 Walker X,可上樓梯、下斜坡、下象棋、柔順力控按摩
阿新 • • 發佈:2021-07-07
題目描述
出題是一件痛苦的事情!
相同的題目看多了也會有審美疲勞,於是我捨棄了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!
好吧,題目是這樣的:給出一串數以及一個數字C,要求計算出所有A - B = C的數對的個數(不同位置的數字一樣的數對算不同的數對)。
輸入格式
輸入共兩行。
第一行,兩個整數N, C。
第二行,N個整數,作為要求處理的那串數。
輸出格式
一行,表示該串數中包含的滿足A - B = C的數對的個數。
輸入輸出樣例
輸入#1 |
輸出#1 |
4 1 1 1 2 3 |
3 |
說明/提示
對於75%的資料,1≤N≤2000。
對於100%的資料,1≤N
保證所有輸入資料絕對值小於2^30。
2017/4/29 新添資料兩組
題目分析
- 資料規模N最大為2e5,普通查詢方式肯定會超時,我們可以先對序列排序,然後用二分查詢查詢資料。
- A – B = C可知,A、B是變數C是常量,那麼我們知道A就可以通過C求B,轉化式子為:A – C = B。
- A是輸入資料中的序列,C是具體數,B是A – C的結果。通過A – C得到的B作為key(要查詢的關鍵詞),在原序列中去尋找是否存在。
- 遍歷時每次判斷得到B是否存在,用一個計數器來記錄存在次數,遍歷完序列後輸出。
- 關鍵的小坑:待查的B結果可能不止一個,所以查詢還得查出B在序列中有幾個。此處可以用下面陳述的程式碼,有空用C++中STL裡的函式upper_bound()和lower_bound函式來確定左右邊界,差值即為B的個數(
可行程式碼
#include <algorithm> #include <iostream> using namespace std; int search(int key, int *arr, int len) { int l = -1, r = len - 1, mid; // 注意的是陣列是從0開始的 while (l + 1 < r) { mid = l + r >> 1; if (arr[mid] <= key) l = mid;else r = mid; } return r; // 返回第一個大於key的位置 } int main() { int NumCount, AimNum; // 序列長度、C的值 cin >> NumCount >> AimNum; int num[NumCount]; for (int i = 0; i < NumCount; i++) cin >> num[i]; long long Sum = 0; // 資料很大 sort(num, num + NumCount); // 二分查詢的前提是序列有序 for (int i = 0; i < NumCount; i++) { int begin = search(num[i] - AimNum - 1, num, i + 1); // 左邊界 int end = search(num[i] - AimNum, num, i + 1); // 右邊界 Sum += end - begin; // 每次查詢結果疊加 } cout << Sum << endl; return 0; }
END感謝reader's閱讀,洛谷題目連結:P1102 A-B 數對 - 洛谷 | 電腦科學教育新生態 (luogu.com.cn)