【BZOJ1720】[Usaco2006 Jan]Corral the Cows 奶牛围栏
Description
Farmer John wishes to build a corral for his cows. Being finicky beasts, they demand that the corral be square and that the corral contain at least C (1 <= C <= 500) clover fields for afternoon treats. The corral's edges must be parallel to the X,Y axes. FJ's land contains a total of N (C <= N <= 500) clover fields, each a block of size 1 x 1 and located at with its lower left corner at integer X and Y coordinates each in the range 1..10,000. Sometimes more than one clover field grows at the same location; such a field would have its location appear twice (or more) in the input. A corral surrounds a clover field if the field is entirely located inside the corral's borders. Help FJ by telling him the side length of the smallest square containing C clover fields.
Input
* Line 1: Two space-separated integers: C and N
* Lines 2..N+1: Each line contains two space-separated integers that are the X,Y coordinates of a clover field.
Output
* Line 1: A single line with a single integer that is length of one edge of the minimum size square that contains at least C clover fields.
Sample Input
1 2
2 1
4 1
5 2
Sample Output
OUTPUT DETAILS:
Below is one 4x4 solution (C's show most of the corral's area); many
others exist.
|CCCC
|CCCC
|*CCC*
|C*C*
+------
题解:二维双指针法的完美结合
双指针法就是令l=1,从1到n枚举右指针r,然后始终保证[l,r]的区间是满足题目要求的区间,不满足就使l++,并每次用[l,r]更新答案(感觉就是简化的单调队列)
如果坐标都是一维的,我们只用双指针法就能搞定,但是由于是二维的,所以我们要用两重双指针法(四指针法。。。)
先二分答案,分别用双指针法维护纵坐标和横坐标,具体还是看代码吧~
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,m,nx,ny; struct field { int x,y; }p[510]; int rx[510],ry[510],s[510]; bool cmp1(field a,field b) { return a.x<b.x; } bool cmp2(field a,field b) { return a.y<b.y; } bool solve(int ml) { int i,a,b,c,d,sc,sd; a=b=0; memset(s,0,sizeof(s)); while(b<n&&rx[p[b+1].x]-rx[1]+1<=ml) s[p[++b].y]++; for(;b<=n;s[p[++b].y]++) { while(rx[p[b].x]-rx[p[a+1].x]+1>ml) s[p[++a].y]--; c=d=sc=sd=0; while(d<ny&&ry[d+1]-ry[1]+1<=ml) sd+=s[++d]; for(;d<=ny;sd+=s[++d]) { while(ry[d]-ry[c+1]+1>ml) sc+=s[++c]; if(sd-sc>=m) return true; } } return false; } int main() { scanf("%d%d",&m,&n); int i; rx[0]=ry[0]=-1; for(i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y); sort(p+1,p+n+1,cmp2); for(i=1;i<=n;i++) { if(p[i].y>ry[ny]) ry[++ny]=p[i].y; p[i].y=ny; } sort(p+1,p+n+1,cmp1); for(i=1;i<=n;i++) { if(p[i].x>rx[nx]) rx[++nx]=p[i].x; p[i].x=nx; } int l=1,r=max(rx[nx],ry[ny]),mid; while(l<r) { mid=l+r>>1; if(solve(mid)) r=mid; else l=mid+1; } printf("%d",r); return 0; }