题目大意:题目题目
给你两组数,要求你对第二组中每一个数计算出第一组中有多少个小于等于它;
题目思路:
数据特点就是数据大而且多,单纯直接找是肯定不行的,这时候突然想到了讲二分时的一道例题:
可以看到跟这个的思路差不多,对第一组数据排序后进行二分查找。注意第一组中可能有重复的数据,就像例子中说的,找到后先不要跳出来标记一下找到最后面的位置;比如排序后第一组数据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;
}
呼呼加油