【POJ 3179】 Corral the Cows

【题目链接】

           http://poj.org/problem?id=3179

【算法】

           首先,我们发现答案是具有单调性的,也就是说,如果边长为C的正方形可以,那么比边长C大的正方形也可以,因此,可以二分答案

           那么,我们怎么检验呢?

           每个点的坐标最大时达到10000,因此,直接二维前缀和显然是会超时的

           考虑将坐标离散化,然后求二维前缀和,由于N<=500,所以离散化后最多也只有1000个点

           检验时,我们枚举正方形的左上角,用二分求出它的右下角,然后,判断正方形内是否有大于C的草量

【代码】

           

#include <algorithm>  
#include <bitset>  
#include <cctype>  
#include <cerrno>  
#include <clocale>  
#include <cmath>  
#include <complex>  
#include <cstdio>  
#include <cstdlib>  
#include <cstring>  
#include <ctime>  
#include <deque>  
#include <exception>  
#include <fstream>  
#include <functional>  
#include <limits>  
#include <list>  
#include <map>  
#include <iomanip>  
#include <ios>  
#include <iosfwd>  
#include <iostream>  
#include <istream>  
#include <ostream>  
#include <queue>  
#include <set>  
#include <sstream>  
#include <stdexcept>  
#include <streambuf>  
#include <string>  
#include <utility>  
#include <vector>  
#include <cwchar>  
#include <cwctype>  
#include <stack>  
#include <limits.h> 
using namespace std;
#define MAXN 510

int C,N,i,j,l,r,mid,ans,tx,ty,len;
int tmp[MAXN<<1],s[MAXN<<1][MAXN<<1],x[MAXN],y[MAXN];

inline int getsum(int xa,int ya,int xb,int yb)
{
        return s[xb][yb] - s[xa-1][yb] - s[xb][ya-1] + s[xa-1][ya-1];
}
inline bool check(int x)
{
        int i,j,tx,ty,pos;
        if (x > tmp[len]) 
    {
        if (s[len][len] >= C) return true;
        else return false;
    }
    pos = upper_bound(tmp+1,tmp+len+1,tmp[len]-x+1) - tmp - 1;
        for (i = 1; i <= pos; i++)
        {
                for (j = 1; j <= pos; j++)
                {
                        tx = upper_bound(tmp+1,tmp+len+1,tmp[i]+x-1) - tmp - 1;
                        ty = upper_bound(tmp+1,tmp+len+1,tmp[j]+x-1) - tmp - 1;
                        if (getsum(i,j,tx,ty) >= C) return true;        
                }        
        }                
        return false;
}

int main() 
{
        
        scanf("%d%d",&C,&N);
        for (i = 1; i <= N; i++)
        {
                scanf("%d%d",&x[i],&y[i]);    
                tmp[++len] = x[i];
                tmp[++len] = y[i];    
        }
        sort(tmp+1,tmp+len+1);
        len = unique(tmp+1,tmp+len+1) - tmp - 1;
        for (i = 1; i <= N; i++)
        {
                tx = lower_bound(tmp+1,tmp+len+1,x[i]) - tmp;
                ty = lower_bound(tmp+1,tmp+len+1,y[i]) - tmp;
                s[tx][ty]++; 
        }
        tmp[++len] = 10001;
        for (i = 1; i <= len; i++)
        {
                for (j = 1; j <= len; j++)
                {
                        s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + s[i][j];
                }
        }
        l = 1; r = 10000;
        while (l <= r)    
        {
                mid = (l + r) >> 1;
                if (check(mid))
                {
                        r = mid - 1;
                        ans = mid;
                } else l = mid + 1;
        }
        printf("%d\n",ans);
         
        return 0;
    
}

 

posted @ 2018-06-29 14:15  evenbao  阅读(1283)  评论(5编辑  收藏  举报