离散化和前缀和以前做过,但是不熟,所以借鉴的lyd的代码(不过好像他也没用二分查找,虽然书上这么写的)不过代码中有一些剪枝和为下一步预处理的的操作可能优化了时间,反正62ms过了。。。
附上代码:
1 #include<cstdio>
2 #include<algorithm>
3 #include<cstring>
4 #include<set>
5 #include<vector>
6 #define INF 1<<30
7 using namespace std;
8 vector<int> X,Y;
9 const int maxn=510;
10 //typedef point pair<int,int>;
11 int sum[maxn][maxn];
12 vector<pair<int,int> >p;
13 int main(){
14 int C,n,x,y;
15 int a,b;
16 scanf("%d%d",&C,&n);
17 for(int i=1;i<=n;i++){
18 scanf("%d%d",&a,&b);
19 p.push_back(make_pair(a,b));
20 X.push_back(a);
21 Y.push_back(b);
22 }
23 //排序
24 sort(p.begin(),p.end());
25 sort(X.begin(),X.end());
26 X.erase(unique(X.begin(),X.end()),X.end());//去重
27 sort(Y.begin(),Y.end());
28 Y.erase(unique(X.begin(),X.end()),X.end());
29 x=X.size(),y=Y.size();
30 X.push_back(INF),Y.push_back(INF);
31 //求二维前缀和
32 //sum[i][j]是点X[i-1][j-1]的前缀和
33 int pos=0;
34 for(int i=1;i<=x;i++){
35 for(int j=1;j<=y;j++){
36 sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
37 while(pos<n&&p[pos].first==X[i-1]&&p[pos].second==Y[j-1]){//判断该点是否有草
38 sum[i][j]++;
39 pos++;
40 }
41 }
42 }
43 //查找
44 int ans=INF;
45 for(int i=0;i<x;i++){//枚举起点x坐标
46 int i1=i+1;//终点x坐标
47 int s=0;//边长
48 int j=0;//起点y坐标
49 int j1=1;//终点y坐标
50 int val=sum[i1][j1]-sum[i][j1]-sum[i1][j]+sum[i][j];
51 while(1){
52 while(val<C&&(i1<x||j1<y)){
53 s=min(X[i1]-X[i],Y[j1]-Y[j]);
54 while(X[i1]-X[i]<=s)i1++;//因为sum[i][j]是坐标(x-1,y-1)的前缀和
55 while(Y[j1]-Y[j]<=s)j1++;
56 val=sum[i1][j1]-sum[i][j1]-sum[i1][j]+sum[i][j];
57 }
58 if(val<C)break;//剪枝
59 ans=min(ans,s+1);
60 j++;//y坐标+1
61 if(j==y)break;//y坐标枚举到头了,退出循环
62 if(j1<=j){
63 j1=j+1;
64 s=0;
65 }
66 else{
67 s-=Y[j]-Y[j-1];//边长也相应的减少
68 }
69 while(X[i1-1]-X[i]>s) i1--;//为下一轮计算做准备
70 val=sum[i1][j1]-sum[i][j1]-sum[i1][j]+sum[i][j];
71 }
72 }
73 printf("%d\n",ans);
74 }