Gym - 101964E -Fishermen(二分+差分求前缀和)

本题出处: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.htmlhttps://blog.csdn.net/Taunt_/article/details/78478526

6、本题的思路很值得我借鉴。这道题我没做出来。

猜你喜欢

转载自blog.csdn.net/an94460061/article/details/83962034