移动通信系统中,通信网的建立主要通过基站来完成。
基站可以分为主基站和子基站。子基站和各个移动用户进行连接,子基站必须通过主基站来和外界实现通信。主基站可以覆盖到的范围是一个圆形区域,子基站和主基站的距离小于半径r才能被该主基站覆盖到。半径r由主基站的发射功率确定。
某个区域的移动通信网,包含2个主基站和N个子基站。它们的位置都可以对应到一个整数坐标上。如果子基站至少被一个主基站覆盖,则该子基站是激活的。
现在通信公司在调试设备,它们不停地改变主基站的发射功率,当两个主基站的覆盖半径分别为r1和r2时,需要知道有多少个子基站处于非激活状态。
有若干组输入数据。
第一行是四个整数:x1、y1、x2、y2(1<=x1、y1、x2、y2<=10^9),表示两个主基站的坐标是(x1,y1)和(x2,y2)。
第二行是一个整数N(1<=N<=100000),表示有N个子基站。
接下来的N行,每行两个整数x、y(1<=x, y<=10^9),表示每个子基站的坐标。
接下来一行包含一个整数M(1<=M<=100000),表示有M个询问。
接下来的M行,每行两个整数r1、r2(1<=r1, r2<=10^9),表示询问当两个主基站的覆盖半径为r1和r2时,处于非激活状态的子基站数。对每个查询,输出答案。
1 10 5 2 5 2 6 1 9 3 8 6 7 4 12 5 1 1 3 2 8 2 2 2 3 2
5 3 0 4 3
将基站到2个主站的距离^2表示成二维坐标
则本题的询问表示成半径^2
本题等价于“平面上有n个点,问n-横坐标<r1或纵坐标<r2的点数".
用树状数组维护,先按照x从小到大插入,询问y值,得到左下角点数->左上角点数。
接着用容斥,求右上角的点数
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<functional> #include<iostream> #include<cmath> #include<cctype> #include<ctime> using namespace std; #define For(i,n) for(int i=1;i<=n;i++) #define Fork(i,k,n) for(int i=k;i<=n;i++) #define Rep(i,n) for(int i=0;i<n;i++) #define ForD(i,n) for(int i=n;i;i--) #define RepD(i,n) for(int i=n;i>=0;i--) #define Forp(x) for(int p=pre[x];p;p=next[p]) #define Lson (x<<1) #define Rson ((x<<1)+1) #define MEM(a) memset(a,0,sizeof(a)); #define MEMI(a) memset(a,127,sizeof(a)); #define MEMi(a) memset(a,128,sizeof(a)); #define INF (2139062143) #define F (100000007) #define MAXN (100000+10) #define MAXXi (1000000000) #define MAXM (100000+10) long long mul(long long a,long long b){return (a*b)%F;} long long add(long long a,long long b){return (a+b)%F;} long long sub(long long a,long long b){return (a-b+(a-b)/F*F+F)%F;} typedef long long ll; int n,X1,Y1,X2,Y2,m,tot; int lowbit(int x){return x&(-x);} ll sqr(ll x){return x*x;} ll dis2(ll x1,ll y1,ll x2,ll y2){return sqr(x1-x2)+sqr(y1-y2);} struct arr_tree { int a[MAXN+MAXM*6]; void reset(){ MEM(a) } void add1(int x) { for(;x<=tot;x+=lowbit(x)) a[x]++; } int sum(int x) { int ans=0; for(;x>0;x-=lowbit(x)) ans+=a[x]; return ans; } }T; struct node { ll x,y; //距离^2 friend bool operator<(node a,node b){return a.x<b.x; } }a[MAXN*2]; struct comm { ll r1,r2; //半径^2 int i; friend bool operator<(comm a,comm b){return a.r1<b.r1; } }ask[MAXM*2]; int ans[MAXM*2]; ll y_[MAXN+MAXM*2]; int loc(ll y) { return lower_bound(y_+1,y_+1+tot,y)-y_; } int main() { while (scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2)==4) { T.reset(); scanf("%d",&n); For(i,n) { int x,y; scanf("%d%d",&x,&y); a[i].x=dis2(x,y,X1,Y1);a[i].y=dis2(x,y,X2,Y2); y_[i]=a[i].y; } sort(a+1,a+1+n); scanf("%d",&m); For(i,m) { int r1,r2; scanf("%d%d",&r1,&r2); ask[i].i=i;ask[i].r1=sqr(r1);ask[i].r2=sqr(r2); y_[n+i]=ask[i].r2; } sort(ask+1,ask+1+m); sort(y_+1,y_+n+m+1); tot=unique(y_+1,y_+n+m+1)-(y_+1); int j=1; For(i,m) { while(j<=n&&a[j].x<ask[i].r1) T.add1(loc(a[j].y)),j++; ans[ask[i].i]=j-1-T.sum(loc(ask[i].r2)-1); } while(j<=n) T.add1(loc(a[j].y)),j++; For(i,m) ans[ask[i].i]+=T.sum(loc(ask[i].r2)-1); For(i,m) printf("%d\n",n-ans[i]); } return 0; }
ACdream 1127(Base Station-树状数组-2个约束条件),布布扣,bubuko.com
ACdream 1127(Base Station-树状数组-2个约束条件)
原文:http://blog.csdn.net/nike0good/article/details/37318551