upper_bound()二分求助

P1678 烦恼的高考志愿

Mandel520 @ 2022-02-15 12:26:44

二分查找的思路是这样的:

首先读入所有学校的分数, 然后对所有学校的分数从小到大排序

然后依次读入所有学生的估分, 然后使用 upper_bound() 函数对当前估分进行二分查找. upper_bound()函数的返回值存入变量 idx, 表示数组中第一个比当前估分更大的值的下标

然后在下标为 idx 的值和下标为 idx - 1 的值之间找到和估分相差较小的值, 将分差累加给总分差

每次查找的结果有三种情况:

(1) 如果当前数组中存在一个和查找的估分相同的值, 则 idx - 1 就是和估分相同的值

(2) 如果当前数组中存在多个和查找的估分相同的值, 则 idx - 1 也是和估分相同的值

(3) 如果当前数组中不存在和查找的估分相同的值, 则 idx - 1是最后一个小于估分的值, idx 是第一个大于估分的值. 在这两个值中, 必定存在和估分分查最小的值

因此, 不管是上面哪种情况, idx 和 idx - 1 对应的值中都必定有一个是和估分相差最小的值

这种思路理论上是没有问题的, 但是除了样例以外都WA了

#include<bits/stdc++.h>
using namespace std;

int scoreline[1000005];
int scores[1000005];
int m, n;
long long sum = 0;

int main(){
    cin >> m >> n;
    for (int i = 1; i <= m; i++) cin >> scoreline[i]; //读入分数线
    sort(scoreline + 1, scoreline + n + 1);

    for (int i = 1; i <= n; i++){ //依次读入学生的估分
        int score;
        cin >> score;
        int idx = upper_bound(scoreline + 1, scoreline + m + 1, score) - scoreline;
        //判断边界
        if (idx == 1) sum += abs(scoreline[idx] - score);
        else if (idx == m + 1) sum += abs(scoreline[idx - 1] - score);
        //取当前学校和前一个学校中分差较小的, 把分差加给总分差
        else sum += min(abs(score - scoreline[idx - 1]), abs(score - scoreline[idx]));
    }

    cout << sum << endl;
    return 0;
}

恳请各位大佬帮我看看问题出在哪


by CANTORSORT @ 2022-02-15 14:17:01

upper_bound 改成手打试试?


by CANTORSORT @ 2022-02-15 14:18:43

int l=0,r=m+1;
while(l<r)
{
    int mid=(l+r)>>1;
    if(scoreline[mid]<=score)
        l=mid+1;
    else
        r=mid;
}

by CANTORSORT @ 2022-02-15 14:26:04

for (int i = 1; i <= m; i++)
    cin>>scoreline[i]; //读入分数线
sort(scoreline + 1, scoreline + n + 1);

by CANTORSORT @ 2022-02-15 14:26:34

sort(scoreline + 1, scoreline + n + 1); 改成 sort(scoreline + 1, scoreline + m + 1);


by CANTORSORT @ 2022-02-15 14:27:47

一打错,千古恨!


by CANTORSORT @ 2022-02-15 14:28:08

跟二分没关系哈~


by Mandel520 @ 2022-02-15 22:37:35

@cantorsort2919 谢谢大佬 Orz


by FireDHK @ 2022-03-10 07:45:14

我的思路跟你的差不多,你的代码能过吗,我的总是有三个WA


|