补给站

Description

  WYF为了保证他自己能够吃到足够多的牛排,来补充自己的脑力,所以他建了两个补给站,坐标分别为 (ax,ay),(bx,by) ( a x , a y ) , ( b x , b y ) 。他有n个休息地点,第i个休息地点的坐标是 (xi,yi) ( x i , y i ) 。每个补给站都有一个补给半径,当一个休息地点在以一个补给站为圆心,该补给站的补给半径为半径的圆中时(包括在圆周上),那个休息地点就会获得补给。现在有  m    m   个询问,每个询问会给出第一个补给站的补给半径  r1    r 1   和第二个补给站的补给半径  r2    r 2   ,WYF想知道有多少个休息地点会得到补给。

Input

  输入的第一行包含  2    2   个整数,  n    n    m   m
  第二行包含  4    4   个整数, ax,ay,bx,by a x , a y , b x , b y
  第  3    3    n+2    n + 2   行包含  2    2   个整数  x,y   x , y
  第  n+3    n + 3    n+m+2    n + m + 2   行包含两个整数  r1,r2   r 1 , r 2

Output

  输出的第  1    1    m    m   行包含  1    1   个整数,表示其所对应的询问的答案。

Data Constraint

  对于 30% 30 % 的数据: n5000,m5000 n ≤ 5000 , m ≤ 5000 .

  对于 100% 100 % 的数据: n2105,m105 n ≤ 2 ∗ 10 5 , m ≤ 10 5 ,
  
  ax,ay,bx,by,x,y[100000,100000],r1,r2[0,300000] a x , a y , b x , b y , x , y ∈ [ − 100000 , 100000 ] , r 1 , r 2 ∈ [ 0 , 300000 ]

Sample Input

4 2
-1 0 2 0
0 0
1 1
2 2
0 2
3 1
1 1  

Sample Output

3
1
【样例说明】
对于第一个询问,第1,2,4个休息点都能受到补给。
对于第二个询问,只有第1个休息点能受到补给。

Solution

  我们设 A(r1){xi|disxia<=r1}B(r2){xi|disxia<=r2} A ( r 1 ) ∈ { x i | d i s ( x i , a ) <= r 1 } ; B ( r 2 ) ∈ { x i | d i s ( x i , a ) <= r 2 }
  则  ANS=A+BAB   A N S = A + B − A ∩ B 。其中A,B是可以直接求得,问题在于求 AB A ∩ B
  在此,我们可用线段树来查询。


  ①将  r1    r 1   由小到大排序,然后将  A    A   也从小到大排序。
  ②枚举 questions q u e s t i o n s ,将A中符合条件的点依次加入线段树中,直到不能加为止。
  而线段树要储存的就是在  0    0   ~ r2 r 2 范围内  A    A   中点出现过的次数。
  ③查询线段树  0    0   ~  r2   r 2 区间的和,即为重复的个数。

Code

const   maxn=300005;
        maxq=100005;
var     n,m,lim,wei,i:longint;
        x1,x2,y1,y2,x,y,bin:int64;
        a,b:real;
        dis:array[0..maxn,1..2] of longint;
        q:array[0..maxq,0..2] of longint;
        ans:array[1..maxq] of longint;
        tr,f1,f2:array[0..2*maxn] of longint;
function max(x,y:longint):longint;
begin
        if x>y then exit(x) else exit(y);
end;
procedure qsort1(x,y:longint);
var     k,i,j:longint;
begin
        i:=x;
        j:=y;
        k:=dis[(x+y) div 2,1];
        repeat
                while dis[i,1]<k do inc(i);
                while dis[j,1]>k do dec(j);
                if i<=j then begin
                        dis[0]:=dis[i];
                        dis[i]:=dis[j];
                        dis[j]:=dis[0];
                        inc(i);
                        dec(j);
                end;
        until   i>j;
        if i<y then qsort1(i,y);
        if j>x then qsort1(x,j);
end;
procedure qsort2(x,y:longint);
var     k,i,j:longint;
begin
        i:=x;
        j:=y;
        k:=q[(x+y) div 2,1];
        repeat
                while q[i,1]<k do inc(i);
                while q[j,1]>k do dec(j);
                if i<=j then begin
                        q[0]:=q[i];
                        q[i]:=q[j];
                        q[j]:=q[0];
                        inc(i);
                        dec(j);
                end;
        until   i>j;
        if i<y then qsort2(i,y);
        if j>x then qsort2(x,j);
end;
procedure jia(v,x,y,z:longint);
var     k:longint;
begin
        if x=y then begin
                inc(tr[v]);
                exit;
        end;
        k:=(x+y) div 2;
        if z<=k then jia(v*2,x,k,z) else jia(v*2+1,k+1,y,z);
        tr[v]:=tr[v*2]+tr[v*2+1];
end;
procedure find(v,x,y,l,r:longint);
var     m:longint;
begin
        if (x=l) and (y=r) then begin
                inc(bin,tr[v]);
                exit;
        end;
        m:=(x+y) shr 1;
        if r<=m then find(v*2,x,m,l,r) else
        if l>m then find(v*2+1,m+1,y,l,r) else begin
                find(v*2,x,m,l,m);
                find(v*2+1,m+1,y,m+1,r);
        end;
end;
procedure make(x,y,z:longint);
begin
        while (wei<n) and (dis[wei+1,1]<=y) do begin
                inc(wei);
                jia(1,0,lim,dis[wei,2]);
        end;
        bin:=0;
        find(1,0,lim,0,z);
        ans[x]:=f1[y]+f2[z]-bin;
end;
procedure init;
begin
         readln(n,m);
        readln(x1,y1,x2,y2);
        for i:=1 to n do begin
                readln(x,y);
                a:=sqrt(sqr(x-x1)+sqr(y-y1));
                b:=sqrt(sqr(x-x2)+sqr(y-y2));
                if a>trunc(a) then dis[i,1]:=trunc(a)+1 else dis[i,1]:=trunc(a);
                if b>trunc(b) then dis[i,2]:=trunc(b)+1 else dis[i,2]:=trunc(b);
                lim:=max(lim,dis[i,2]);
                inc(f1[dis[i,1]]);
                inc(f2[dis[i,2]]);
        end;
        for i:=2 to maxn do begin
                inc(f1[i],f1[i-1]);
                inc(f2[i],f2[i-1]);
        end;
        for i:=1 to m do begin
                readln(q[i,1],q[i,2]);
                q[i,0]:=i;
        end;
end;
begin

        init;
        qsort1(1,n);
        qsort2(1,m);
        wei:=0;
        for i:=1 to m do make(q[i,0],q[i,1],q[i,2]);
        for i:=1 to m do writeln(ans[i]);

end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值