http://poj.org/problem?id=2464
题意:
在平面直角坐标系中给你N个点,stan和ollie玩一个游戏,首先stan在竖直方向上画一条直线,该直线必须要过其中的某个点,然后ollie在水平方向上画一条直线,该直线的要求是要经过一个stan之前画过的点。 这时候平面就被分割成了四块,两个人这时候会有一个得分,stan的得分是平面上第1、3象限内的点的个数,ollie的得分是平面上第2、4象限内的点的个数,在统计的时候在所画线上的点都不计算在内。求最终stan使得自己的最差得分最高,并且输出此时ollie的得分。
思路:
这题其实也数星星那题基本思路是一样的,题目的关键就是要求出在给定一个点之后,如何求出其四个象限内的点的个数。求出之后依次枚举最大值的出现位置和ollie可能的值。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#define MIN(a,b) ( (a)>(b)?(b):(a) )
int N ;
const int MAXN = 200010 ;
struct Node{
int x ,y ;
}p[MAXN] ;
bool comp(Node n1 , Node n2){
if(n1.x == n2.x ) return n1.y > n2.y ;
else return n1.x < n2.x ;
}
int x[MAXN] , y[MAXN] ;
int xn , yn ;
int xnum[MAXN] ,ynum[MAXN] ;
int xsum[MAXN] , ysum[MAXN] ;
int findx(int v , int l , int r){
while(l<r){
int mid = (l + r) >> 1 ;
if( x[mid] < v ) l = mid + 1;
else r = mid ;
}
return l ;
}
int findy(int v , int l ,int r){
while( l<r ){
int mid = (l + r)>> 1 ;
if( y[mid] < v ) l = mid + 1 ;
else r = mid ;
}
return l ;
}
int C[MAXN] ;
int lowbit(int x){
return ( x&(x^(x-1)) ) ;
}
void add(int n){
while( n<=N ){
C[n]++ ;
n += lowbit(n);
}
}
int sum(int n){
int res = 0 ;
while( n>=1 ){
res += C[n] ;
n -= lowbit(n) ;
}
return res ;
}
int stan[MAXN] ;
std::vector<int> ol[MAXN] ;
void sovle(){
std::sort( p+1, p+N+1 ,comp);
memset( C , 0 ,sizeof(C) );
for(int i=1;i<=N;i++){
stan[i] = N + 1 ;
ol[i].clear() ;
}
for(int i=1;i<=N;i++){
int x = findx( p[i].x , 1, xn );
int y = findy( p[i].y , 1 ,yn );
add(y) ;
int a = sum(y-1) ;
int b = N - ysum[y] - ( i - sum(y) ) ;
int c = N - a - b - xnum[x] - ynum[y] + 1 ;
stan[x] = MIN( stan[x] , a + b);
ol[x].push_back( c ) ;
}
int _max = -1 ;
for(int i=1;i<=xn;i++){
if( _max < stan[i] ) _max = stan[i] ;
}
bool is_ok[MAXN] ;
memset(is_ok , 0 ,sizeof(is_ok));
for(int i=1;i<=xn;i++){
if( _max == stan[i] ) {
for(int j=0;j<ol[i].size();j++)
is_ok[ ol[i][j] ] = 1 ;
}
}
printf("Stan: %d; Ollie:",_max);
for(int i=0;i<=N;i++)
if(is_ok[i]) printf(" %d",i);
printf(";\n");
}
int main(){
while( scanf("%d",&N) && N ){
for(int i=1;i<=N;i++){
scanf("%d%d",&p[i].x , &p[i].y );
x[i] = p[i].x ; y[i] = p[i].y ;
}
std::sort(x+1 , x+N+1);
std::sort(y+1 , y+N+1);
xn = yn = 2 ;
for(int i=2;i<=N;i++){
if( x[i] != x[i-1] ) x[xn++] = x[i] ;
}
for(int i=2;i<=N;i++){
if( y[i] != y[i-1] ) y[yn++] = y[i] ;
}
xn -- ; yn -- ;
memset(xnum , 0 ,sizeof(xnum) );
memset(ynum , 0 ,sizeof(ynum) );
for(int i=1;i<=N;i++){
int s = findx(p[i].x , 1 ,xn ) ;
xnum[s] ++ ;
}
xsum[0] = 0 ;
for(int i=1;i<=xn;i++)
xsum[i] = xsum[i-1] + xnum[i] ;
for(int i=1;i<=N;i++){
int s = findy(p[i].y , 1 ,yn );
ynum[s] ++ ;
}
ysum[0] = 0 ;
for(int i=1;i<=yn;i++){
ysum[i] = ysum[i-1] + ynum[i] ;
}
sovle() ;
}
return 0 ;
}