bzoj1720: [Usaco2006 Jan]Corral the Cows 奶牛围栏

时间:2023-03-08 18:11:49

金组题什么的都要绕个弯才能AC。。不想银组套模板= =

题目大意:给n个点,求最小边长使得此正方形内的点数不少于c个

首先一看题就知道要二分边长len

本来打算用二维前缀和来判断,显然时间会爆,而且坐标最大10000是不可行的

为保证效率,检验的时间应该在O(n2

所以我们先给x排个序,以每个点的x坐标为左边界,x+len-1为右边界

然后以y为关键字从小到大序后枚举点,用双指针法O(n)更新len以内能保存多少个点

点数大于等于c就可行

 #include<stdio.h>
 #include<string.h>
 #include<algorithm>
 using namespace std;
 ;
 int x[maxn],y[maxn],l,r,a[maxn],b[maxn],c,n;

 bool cmp1(int a, int b){return x[a]<x[b];}
 bool cmp2(int a, int b){return y[a]<y[b];}

 bool check(int len){
     ;
     ; i<=n; i++){
         left=x[a[i]]; right=left+len-;
         ans=;
         ;
         ; j<=n; j++){
             <=len && k<=n){
                 if (x[b[k]]>=left && x[b[k]]<=right) {
                     ans++;
                 //    printf("  %d %d %d %d %d\n", x[b[j]], x[b[k]], y[b[j]], y[b[k]], ans);
                 }
                 k++;
             }
         //    printf("%d %d %d %d %d\n", left, right, y[b[j]], y[b[j]]+len-1, ans);
             ;
             if (x[b[j]]>=left && x[b[j]]<=right) ans--;
         }
     }
     ;
 }

 int main(){
     scanf("%d%d", &c, &n);
     ; i<=n; i++){
         scanf("%d%d", &x[i], &y[i]);
         r=max(r,x[i]); r=max(r,y[i]);
         a[i]=b[i]=i;
     }
     sort(a+,a++n,cmp1);//x从小到大 枚举列
     sort(b+,b++n,cmp2);//y从小到大 枚举行
     l=;
     ;
     while (l<=r){
         ;
         ;
         ;
     }
     printf("%d\n", ans);
     ;
 }