今天考試做了道題,用上了map,這是一道提高組聯賽難度的題目,先發題目:
******************************
1. A-B problem
( dec.c/cpp/pas) .
Description
大家都非常熟悉 A+B Problem! 題目看多了也有審美疲勞,於是我舍棄了,改用 A-B problem! 題目是這樣的:給出一串數以及一個數字 C,要求計算出所有 A-B=C 的數對 的個數。( 注意: 不同位置的數字一樣的數對算不同的數對)
Input Format
第一行包括 2 個非負整數 N 和 C,中間用空格隔開。 第二行有 N 個整數,中間用空格隔開,作為要求處理的那串數。
Output Format
輸出一行,表示該串數中包含的所有滿足 A-B=C 的數對的個數。
Sample Input
4 1
1 1 2 3
Sample Output
3
Data Limit
對於 50%的數據, N <= 2000; 對於 100%的數據, N <= 200000。
******************************
看到這題,第一反應就是用桶,多方便啊。可是看到這里的數據規定:長整型……相信不會再有人用普通的數組來做桶了。
這里我機智地用到了一種對象:map。
map,將鍵映射到值的對象。
比如你需要把日期轉為數字,比如把"7月30日"轉換為730,怎么轉換呢?
別的麻煩辦法我就不說了,說下map怎么實現:
先定義一個map:
map<string,int>date;
嗯,尖括號里的那個string代表date這個map的鍵(KEY)是字符串型的,而string后面那個int表示date所映射存儲的值是整數。
然后我們定義:
date["7月30日"]=730;
OK,完事了。
之后要輸出的話:
cout<<date["7月30日"];
下面貼出將字符串日期轉換為數字的完整代碼:
#include <iostream> #include <map> using namespace std; map<string,int>date; int main() { date["7月30日"]=730; cout<<date["7月30日"]; return 0; }
沒錯就是這么愉快與簡單就完事了。
明白了map的用法我們回到題目。
咱們定義一個map桶:
map<long,int>m;
這個桶的用法(就是普通的桶的用法):m[i]表示數字i出現的次數。
如果我們用普通數組,那么根據題意,我們定義的數組的成員個數至少為2147483647,就是長整型的最大值。
而map為什么不會超呢?因為map是映射,它那個中括號里的數字只是一個鍵(這說起來很復雜……)……唉,口頭表達能力不行,簡單了說吧,就是說map你沒有定義過某個鍵,它就不會占用空間,當你去映射一個沒有訪問過的鍵時,它會自動返回0。等於是說map桶去除了所有的空桶所占的空間。那么這題中我們只會用到<=200000個桶。
貼上代碼:
#include <cstdio> #include <map> using namespace std; map<long,int> m;//咱們的map桶 int n; long c,num[200005]; int main() { scanf("%d%ld",&n,&c);//n個數字,c是差值 int ans=0,i=n; while(i--) { scanf("%d",&num[i]); m[num[i]]++;//裝到桶里去~ } i=n; if(c>0)//特判0 while(i--) ans+=m[num[i]+c]; else while(i--) ans=ans+m[num[i]+c]-1;//當c為0時每個數字還得排掉自己呢~ printf("%d",ans); return 0; }
這里只用了25行,就打完了整個題目。看着別的童鞋打個幾十行代碼還沒法AC,心里樂呵呀~
不過說一下,這樣的算法時間復雜度是nlogn,因為map讀取的速度是logn,所以速度不是很快。話說最快是二分+縮點,有興趣的童鞋可以去做做。
最后說一下:STL大發好,退C轉C++保平安……