1. 程式人生 > 其它 >P1102 A-B 數對 (map,lower_bound&upper_bound)

P1102 A-B 數對 (map,lower_bound&upper_bound)

題目描述

出題是一件痛苦的事情!

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

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

輸入格式

輸入共兩行。

第一行,兩個整數 N,C

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

輸出格式

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

輸入輸出樣例

輸入 #1
4 1
1 1 2 3
輸出 #1
3

說明/提示

對於 75%的資料,1≤N≤2000

對於 100% 的資料,1≤N≤2×1e5

保證所有輸入資料絕對值小於 2^{30}

2017/4/29 新添資料兩組

比較水的一道題,重點講一下map,lower_bound,upper_bound的使用

map

定義map<a,b>,a,b是資料型別,包括但不限於int等數字型別,string類,char類,甚至是stl內的其他型別,比如棧,堆,佇列等等等等,map會建立這兩個資料型別間的一一對映

在這個題裡,map作為常規陣列桶的上位替代,極大的優化了空間

lower_bound&lower_bound

定義lower_bound(a+1,a+1+n,x)-a,返回值代表,在陣列a中,從1到n的範圍內,第一個小於等於x的數字

定義upper_bound(a+1,a+1+n,x)-a,返回值代表,在陣列a中,從1到n的範圍內,第一個小於x的數字

由於本質是二分查詢,因此這兩個函式都需要保證陣列中的數是不遞減序列

說一下思路

核心思路是把a-b=c轉化為a=b+c,在此基礎上延伸處兩個思路

第一個思路是桶排

o(n)的列舉一遍b,只要bus[b+c]不為空就把bus[b]*bus[b+c]加到答案裡

第二個思路是排序+lower_bound+upper_bound

同樣o(n)的列舉一遍b,用upper_bound和lower_bound去找b+c,upper_bound減去lower_bound的結果就是b+c這個數字的個數,累加到答案

程式碼如下

#include<bits/stdc++.h>
using namespace std; long long a[200005],n,c,ans; map<long long,long long> m; int main()
{
cin >> n >> c; for(int i=1;i<=n;i++) { cin >> a[i]; m[a[i]]++; a[i]+=c; } for(int i=1;i<=n;i++) ans+=m[a[i]]; cout << ans << endl; return 0; }