CodeForces - 600B Queries about less or equal elements (需要标记位置的二分)

题目大意:题目题目

  给你两组数,要求你对第二组中每一个数计算出第一组中有多少个小于等于它;

题目思路:

  数据特点就是数据大而且多,单纯直接找是肯定不行的,这时候突然想到了讲二分时的一道例题:

   可以看到跟这个的思路差不多,对第一组数据排序后进行二分查找。注意第一组中可能有重复的数据,就像例子中说的,找到后先不要跳出来标记一下找到最后面的位置;比如排序后第一组数据1 1 2 2 2,第二组计算的数据是2,那么第一次二分的位置在第三,此时2=2,但是不能直接return,显然答案并不是3,因为后面还有重复的数;那么我们可以考虑判断一下后面一位是不是相同的数字(因为已经经过排序,如果后面一位不相同,后面肯定不会有重复的了),如果有重复,就继续队后面进行二分;

AC代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define maxn 200005
#define INF 999999999

using namespace std;
long long a[maxn],b[maxn];
long long res[maxn];
int n,m;

int finds(long long x)
{
    int left=0;
    int right=n-1;
    int ans=-INF;
    int flag=1;
    while(right>=left)//二分的过程
    {
        //printf("mm\n");
        int mid=(right-left)/2+left;
        if(a[mid]>x)
        {
            right=mid-1;
        }
        else if(a[mid]<x)
        {
            left=mid+1;
        }
        else if(a[mid]==x)
        {
            ans=max(ans,mid+1);
            if(a[mid+1]==a[mid])//如果后一位是重复的需要继续二分
                left=mid+1;
            else
                return mid+1;//不用考虑前面是不是有重复,因为我们要找最大的位置,此时可以直接return
            flag=0;
        }
    }
    if(flag)
        ans=max(ans,left);
    return ans;
}
int main(void)
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%lld",&a[i]);
    }
    sort(a,a+n);
    for(int i=0;i<m;i++)
    {
        scanf("%lld",&b[i]);
        res[i]=finds(b[i]);
    }
    for(int i=0;i<m;i++)
    {
        if(i)
            printf(" ");
        printf("%d",res[i]);
    }
    printf("\n");
    return 0;
}

呼呼加油

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81202109
今日推荐