提交链接:http://codeforces.com/gym/101964/problem/E
题面链接:https://vj.e949.cn/d8a88a967901013f7b7fe74f87ec1001?v=1542096019
题意:有条鱼,给出每条鱼的坐标,有个人每个人都在横轴上坐标为,第个人与第条鱼的距离为,现在每个人都有一个长为的鱼竿,问对每个人有多少鱼在自己的鱼竿范围之内。
解析:想到对于每条鱼求一个,表示在岸边的坐标范围内能够到此鱼,这里由于区间很大,要进行一下离散化,区间更新时二分分别找到和(直接使用lower_bound()函数也行),使得是大于等于坐标的最靠左的人,是小于等于坐标的最靠右的人。然后对进行一个区间更新即可。
代码(296ms):
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN=2e5+50;
struct Fish
{
ll x,y;
}f[MAXN];
struct People
{
ll x,id;
bool operator <(const People& obj)const
{
return x<obj.x;
}
}p[MAXN];
ll n,m,l,ans[MAXN];
ll where[MAXN],tp[MAXN];//tp[]用于lower_bound
ll Find1(ll x)
{
if(x>p[m].x) return -666;
return ((lower_bound(tp+1,tp+m+1,x))-(tp));
}
ll Find2(ll x)
{
if(x<p[1].x) return -666;
return ((upper_bound(tp+1,tp+m+1,x))-(tp));
}
int main()
{
ll L,R;
scanf("%I64d%I64d%I64d",&n,&m,&l);
for(ll i=1;i<=n;i++)
scanf("%I64d%I64d",&f[i].x,&f[i].y);
for(ll i=1;i<=m;i++)
{
scanf("%I64d",&p[i].x);
p[i].id=i;
}
sort(p+1,p+1+m);
for(ll i=1;i<=m;i++)
{
where[p[i].id]=i;
tp[i]=p[i].x;
}
for(ll i=1;i<=n;i++)
{
if(f[i].y>l) continue;
L=f[i].x-(l-f[i].y);
R=f[i].x+(l-f[i].y);
//cout<<i<<" "<<L<<" "<<R<<" ";
L=Find1(L);
if(L==-666) continue;
R=Find2(R);
if(R==-666) continue;
R--;
//cout<<L<<" "<<R<<endl;
ans[L]++;
ans[R+1]--;
}
for(ll i=1;i<=m;i++)
ans[i]+=ans[i-1];
for(ll i=1;i<=m;i++)
printf("%I64d\n",ans[where[i]]);
return 0;
}