P1102 A-B数对 (二分查找)

题目链接:P1102

解题思路:

要找A-B=C,变成A=B+C,将数排序,遍历每一个数,用二分查找查看是否存在B+C,因为不同位置数字算不同一对,所以要特殊处理,开数组记录的话可能会MLE,所以用map来存数字出现次数

AC代码:

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <map>
 5 #define ll long long
 6 using namespace std;
 7 ll n,c,mx,cnt,a[300010];
 8 inline ll read() // 快读
 9 {
10     ll x = 0,y = 1; char c = getchar();
11     while(c < '0' || c > '9') {if(c == '-') y = -1; c = getchar();}
12     while(c >= '0' && c <= '9') x = x*10+c-'0', c = getchar();
13     return x*y;
14 }
15 bool bfind(ll x) // 二分
16 {
17     int l = 0, r = n-1;
18     int mid = (r-l)/2+l;
19     while(true)
20     {
21         if(l == r)
22         {
23             if(a[l] == x) return true;
24             else return false;
25         }
26         if(a[mid] >= x)
27         {
28             r = mid;
29             mid = (r-l)/2+l;
30         } else if(a[mid] < x) {
31             l = mid+1;
32             mid = (r-l)/2+l;
33         }
34     }
35 }
36 int main()
37 {
38     map<ll, ll> m;
39     cnt = 0;
40     n = read();
41     c = read();
42     for(int i = 0; i < n; i++)
43     {
44         a[i] = read();
45         m[a[i]]++; // 记录出现次数
46     }
47     sort(a,a+n);
48     mx = a[n-1]; // 记录一下最大值
49     for(int i = 0; i < n; i++)
50     {
51         if(a[i]+c > mx) continue; // 如果超过最大值,就没必要去查找了
52         else if(bfind(a[i]+c))
53             cnt += 1*m[a[i]+c]; // 算不同位置的对数
54     }
55     printf("%lld",cnt);
56     return 0;
57 }

 

posted @ 2020-09-12 22:22  不敢说的梦  阅读(542)  评论(0)    收藏  举报