金组题什么的都要绕个弯才能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); ; }