本题出处:2018-2019 ACM-ICPC东南欧洲区域编程竞赛(SEERC 2018)
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. (上图为上面的例子所示,第三个渔民可以在这个区域捕鱼。)
本题题意:
有n条鱼,m个渔夫,且这m个渔夫都在横坐标轴上,每个渔夫都有一个长度为l的鱼竿,当鱼和渔夫距离小于或等于l时,鱼能被钓到。
并且渔夫(x,0)与鱼(a,b)的距离(假设为L)满足如下公式 |a − x| + b. 式子中x为渔夫的横坐标,(a,b)为鱼的坐标。
求解思路:
这道题肯定以鱼为考虑的对象。先对公式 |a − x| + b入手。设l≤|a − x| + b.可求出鱼能被钓到时渔夫x的一个范围a+l-b≤x≤a-l+b.然后把渔夫的位置排个序,遍历所有的鱼,每一条鱼能够被可以被抓都在x轴有一个范围(a+l-b≤x≤a-l+b.).通过二分,在渔夫中找到最左的和最右的,然后差分一下,最后求个前缀和就可以得出答案。(正确的思路)
上面的思路是借鉴网上的。我一开始做的思路是用暴力求解 但是也是遍历每条鱼 但是求每个渔夫能抓到鱼的个数时没用差分求前缀和的方法,导致超时。这是网上的题解。http://www.cnblogs.com/Chen-Jr/p/9879980.html
AC代码:(借鉴网上的)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
struct fish
{
int x,y;
}f[maxn];
struct yufu{
int x,id,idd;///id表示输入时的序号。idd表示排序之后的序号
bool operator <(const yufu &bb)const///重载<运算符 为了能够用sort进行排序
{
return x<bb.x;
}
}ma[maxn];
int sum[maxn],ans[maxn];
int main()
{
int n,m,l;
scanf("%d %d %d",&n,&m,&l);
memset(sum,0,sizeof(sum));
for (int i=1;i<=n;i++)
scanf("%d %d",&f[i].x,&f[i].y);
for (int i=1;i<=m;i++)
{
scanf("%d",&ma[i].x);
ma[i].id=i;
}
sort(ma+1,ma+m+1);///排序
for (int i=1;i<=m;i++)
ma[i].idd=i;
for (int i=1;i<=n;i++)
{
if (f[i].y-l>0) continue;///当距离超过l时continue掉
yufu tmp;
tmp.x=f[i].x-l+f[i].y;///二分法
int xx=lower_bound(ma+1,ma+m+1,tmp)-ma;///注意一点用这两个函数时,tmp和ma必须是同类型的
tmp.x=f[i].x+l-f[i].y;
int yy=upper_bound(ma+1,ma+m+1,tmp)-ma;
sum[xx]++;
sum[yy]--;
}
for (int i=1;i<=m;i++)///用差分法求前缀和
{
sum[i]+=sum[i-1];
ans[ma[i].id]=sum[ma[i].idd];
}
for (int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}
知识点:
1、关于重载运算符:bool
operator <(
const
node &a)
const
{//重载<操作符。可以对两个node使用<操作符进行比。格式类型:
<返回类型说明符> operator <运算符符号>(<参数表>) { <函数体> } 。详细可以百度了解。
2、关于sort函数的使用。
3、关于这两个函数lower_bound、upper_bound。lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。lower_bound( ):查找第一个大于或等于的数字。upper_bound( ):查找第一个大于的数字。详细可见:https://blog.csdn.net/qq_40160605/article/details/80150252
4、二分法的运用。百度
5、差分和前缀和。这两个网站都挺好的https://www.cnblogs.com/OIerShawnZhou/p/7348088.html和https://blog.csdn.net/Taunt_/article/details/78478526
6、本题的思路很值得我借鉴。这道题我没做出来。