Problem Description
The ocean can be represented as the first quarter of the Cartesian plane. There are n fish in the ocean. Each fish has its own coordinates. There may be several fish at one point.
There are also m fishermen. Each fisherman has its own x-coordinate. The y-coordinate of each fisherman is equal to 0.
Each fisherman has a fishing rod of length l. Therefore, he can catch a fish at a distance less than or equal to l. The distance between a fisherman in position x and a fish in position (a, b) is |a − x| + b.
Find for each fisherman how many fish he can catch.
Input
第一行三个整数n,m,l,分别是鱼的个数,渔夫的个数,鱼竿的长度。(1<=n,m<=2*105,1<=l<=109)
接下来n行,分别为xi,yi,(1<=xi,yi<=109)为鱼的坐标
再一行,分别为ai,(1<=ai<=109),为渔夫的位置
Output
For each fisherman, output the number of fish that he can catch, on a separate line.
Sample Input
8 4 4
7 2
3 3
4 5
5 1
2 2
1 4
8 4
9 4
6 1 4 9
Sample Output
2
2
3
2
Note
The picture illustrates for the above example the area on which the third fisherman can catch fish.
#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int x[200000],y[200000],wei[200000],yv[200000]={0};
struct fisher{
int yvf;
int No;
bool operator<(const fisher&x) const
{return yvf<x.yvf;
}
fisher(int y,int n):yvf(y),No(n){
}
fisher(){
}//自定义构造函数后,默认构造函数便不起作用,所以要自己再写一个
};
fisher f[200000];
int main()
{
int n,m,l,le,ri;
cin>>n>>m>>l;
for(int i=0;i<n;i++) scanf("%d%d",&x[i],&y[i]);
for(int i=0;i<m;i++){
scanf("%d",&f[i].yvf);
f[i].No=i;
}
sort(f,f+m);
for(int i=0;i<n;i++) {
if(y[i]>l) continue;
le=x[i]-(l-y[i]);
ri=x[i]+(l-y[i]);
int wl=lower_bound(f,f+m,fisher(le,0))-f;
//结构体使用lower_bound时候,注意要把要比较的数用结构体fisher封装
int wr=upper_bound(f,f+m,fisher(ri,0))-f;
if(wl<m) yv[wl]++;
if(wr<m) yv[wr]--;
}
wei[f[0].No]=yv[0];
for(int i=1;i<m;i++)
{
yv[i]=yv[i]+yv[i-1];
wei[f[i].No]=yv[i];
}
for(int i=0;i<m;i++)
cout<<wei[i]<<'\n';
return 0;
}
本题采用前缀标记法才记录渔夫是否可捕捉到某一条鱼
在从小到大的排序数组中,
lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。*