暑期第四次题目E Fishermen

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,得到找到数字在数组中的下标。*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值