zoukankan      html  css  js  c++  java
  • 洛谷-P1102 A-B 数对

    题目描述

    出题是一件痛苦的事情!

    相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 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≤2e5。

    保证所有输入数据绝对值小于 2^30。

    2017/4/29 新添数据两组

      题目分析

    1. 数据规模N最大为2e5,普通查找方式肯定会超时,我们可以先对序列排序,然后用二分查找查找数据。
    2. A – B = C可知,A、B是变量C是常量,那么我们知道A就可以通过C求B,转化式子为:A – C = B。
    3. A是输入数据中的序列,C是具体数,B是A – C的结果。通过A – C得到的B作为key(要查找的关键词),在原序列中去寻找是否存在。
    4. 遍历时每次判断得到B是否存在,用一个计数器来记录存在次数,遍历完序列后输出。
    5. 关键的小坑:待查的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)

  • 相关阅读:
    【BZOJ3144】切糕(HNOI2013)-最小割
    【BZOJ1934】善意的投票(SHOI2007)-最小割
    【BZOJ2125】最短路-圆方树+倍增LCA
    【BZOJ4868】期末考试(六省联考2017)-三分
    【BZOJ1951】古代猪文(SDOI2010)-数论大集合
    【BZOJ2257】瓶子和燃料(JSOI2009)-裴蜀定理+排序
    【BZOJ1485】有趣的数列(HNOI2009)-卡特兰数+线性筛
    【51Nod1952】栈-单调栈+单调队列
    【BZOJ4517】排列计数(SDOI2016)-组合数学:错排
    【BZOJ2111】排列计数(ZJOI2010)-DP+Lucas定理
  • 原文地址:https://www.cnblogs.com/kirk-notes/p/14994865.html
Copyright © 2011-2022 走看看