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 ; }