【ACDream】1127 Base Station 树状数组

Base Station

Time Limit:20000/10000 MS (Java/Others)Memory Limit:512000/256000 KB (Java/Others)

Problem Description

【ACDream】1127 Base Station 树状数组_第1张图片

 

移动通信系统中,通信网的建立主要通过基站来完成。

基站可以分为主基站和子基站。子基站和各个移动用户进行连接,子基站必须通过主基站来和外界实现通信。主基站可以覆盖到的范围是一个圆形区域,子基站和主基站的距离小于半径r才能被该主基站覆盖到。半径r由主基站的发射功率确定。

某个区域的移动通信网,包含2个主基站和N个子基站。它们的位置都可以对应到一个整数坐标上。如果子基站至少被一个主基站覆盖,则该子基站是激活的。

现在通信公司在调试设备,它们不停地改变主基站的发射功率,当两个主基站的覆盖半径分别为r1和r2时,需要知道有多少个子基站处于非激活状态。

 

 

 

Input

有若干组输入数据。

第一行是四个整数: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时,处于非激活状态的子基站数。

Output

对每个查询,输出答案。

Sample Input

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

Sample Output

5
3
0
4
3

Source

kuangbin

Manager

Dshawn

传送门:
【ACDream】1127 Base Station

题目分析:
因为只要被任意一个主基站覆盖到就算激活,所以未激活的子基站数等于:子基站数-被主基站1覆盖的子基站数-被主基站2覆盖的子基站数+同时被两个主基站覆盖的子基站数。
首先对坐标进行转化,对到主基站1(x1,y1)的距离转化为X轴,对到主基站2(x2,y2)的距离转化为Y轴,以距离的平方作为新的距离(保证精度),同时离线询问。之后对X轴离散化并且将查询和子基站按照Y轴升序排序。然后按照Y轴从小到大插入子基站到树状数组中并查询,注意必须是“小于”。其中子基站数就是n,被主基站1覆盖的子基站数可以通过预处理前缀和得到,被主基站2覆盖的子基站数就是插入的子基站数,同时覆盖的子基站数通过树状数组求和得到。最后问题得到解决。

下面还有另一种思路,在离散化以后,按照Y轴降序排序,这样插入到树状数组的只是没有被任何主基站包含的子基站(也就是未激活的子基站),树状数组求和就是答案,比上面的更简单。

下面给出第一种思路的代码。

代码如下:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std ;

#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REPV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define clear( a , x ) memset ( a , x , sizeof a )
#define mid ( ( l + r ) >> 1 )
#define lowbit( I ) ( ( I ) & -( I ) )

typedef long long LL ;

const int MAXN = 100005 ;

struct Point {
	LL x , y ;
	int idx ;
} ;

Point a[MAXN] ;
Point ask[MAXN] ;
LL aa[MAXN << 1] ;
int c[MAXN << 1] ;
int ans[MAXN] ;
int num[MAXN << 1] ;

LL dist ( LL x , LL y ) {
	return x * x + y * y ;
}

int cmp ( const Point &a , const Point &b ) {
	return a.y < b.y ;
}

int unique ( LL a[] , int n ) {
	int cnt = 1 ;
	sort ( a + 1 , a + n + 1 ) ;
	for ( int i = 2 ; i <= n ; ++ i ) if ( a[i] != a[cnt] ) a[++ cnt] = a[i] ;
	return cnt ;
}

int binary_Search ( LL x , int l , int r ) {
	while ( l < r ) {
		int m = mid ;
		if ( aa[m] >= x ) r = m ;
		else l = m + 1 ;
	}
	return l ;
}

void add ( int x , int n ) {
	for ( int i = x ; i <= n ; i += lowbit ( i ) ) ++ c[i] ;
}

int sum ( int x ) {
	int ans = 0 ;
	for ( int i = x ; i > 0 ; i -= lowbit ( i ) )
		ans += c[i] ;
	return ans ;
}

void debug ( int n , int m , int cnt ) {
	printf ( "%d\n" , cnt ) ;
	REPF ( i , 1 , cnt ) printf ( "%lld " , aa[i] ) ;
	printf ( "\n" ) ;
	REPF ( i , 1 , n ) printf ( "%lld %d |||" , a[i].x , a[i].idx ) ;
	printf ( "\n" ) ;
	REPF ( i , 1 , m ) printf ( "%lld %d |||" , ask[i].x , ask[i].idx ) ;
	printf ( "\n" ) ;
	REPF ( i , 1 , n ) printf ( "y = %lld " , a[i].y ) ;
	printf ( "\n" ) ;
	REPF ( i , 1 , m ) printf ( "y = %lld " , ask[i].y ) ;
	printf ( "\n" ) ;
}

LL read () {
	LL x = 0 ;
	char c = ' ' ;
	while ( c < '0' || c > '9' ) c = getchar () ;
	while ( c >= '0' && c <= '9' ) x = x * 10 + c - '0' , c = getchar () ;
	return x ;
}

void work () {
	LL x1 , x2 , y1 , y2 , x , y ;
	int n , m ;
	int cnt ;
	while ( ~scanf ( "%lld%lld%lld%lld" , &x1 , &y1 , &x2 , &y2 ) ) {
		scanf ( "%d" , &n ) ;
		cnt = 0 ;
		clear ( c , 0 ) ;
		clear ( num , 0 ) ;
		REPF ( i , 1 , n ) {
			x = read () , y = read () ;
			a[i].x = dist ( x - x1 , y - y1 ) ;
			a[i].y = dist ( x - x2 , y - y2 ) ;
			aa[++ cnt] = a[i].x ;
		}
		scanf ( "%d" , &m ) ;
		REPF ( i , 1 , m ) {
			ask[i].x = read () , ask[i].y = read () ;
			ask[i].x *= ask[i].x ;
			ask[i].y *= ask[i].y ;
			aa[++ cnt] = ask[i].x ;
		}
		cnt = unique ( aa , cnt ) ;
		REPF ( i , 1 , n ) {
			a[i].x = binary_search ( a[i].x , 1 , cnt + 1 ) ;
			//a[i].idx = i ;//no meaningful
			++ num[a[i].x] ;
		}
		REPF ( i , 1 , cnt ) num[i] += num[i - 1] ;
		REPF ( i , 1 , m ) {
			ask[i].x = binary_search ( ask[i].x , 1 , cnt + 1 ) ;
			ask[i].idx = i ;
		}
		sort ( a + 1 , a + n + 1 , cmp ) ;
		sort ( ask + 1 , ask + m + 1 , cmp ) ;
		//debug ( n , m , cnt ) ;
		int j = 1 ;
		REPF ( i , 1 , m ) {
			while ( j <= n && a[j].y < ask[i].y ) add ( a[j ++].x , cnt ) ;
			ans[ask[i].idx] = n + sum ( ask[i].x - 1 ) - j + 1 - num[ask[i].x - 1] ;
		}
		REPF ( i , 1 , m ) printf ( "%d\n" , ans[i] ) ;
	}
}

int main () {
	work () ;
	return 0 ;
}


你可能感兴趣的:(树状数组,ACdream)