题目链接:upc2525: Twinkle Twinkle Little Star
Twinkle, twinkle, little star, how I wonder what you are.
Up above the world so high, like a diamond in the sky.
Twinkle, twinkle, little star, how I wonder what you are.
When the blazing sun is gone, when he nothing shines upon.
The you show your little light, Twinkle, twinkle, little star
Twinkle, twinkle, little star, How I wonder what you are.
Twinkle, twinkle, little star, how I wonder what you are.
----<Twinkle, twinkle, little star.>
Well, this song may take us back to our childhood. When we were young, we often looked up at the stars. How amazing they were! But, unfortunately, as we are becoming older and older, what used to be interesting can not interest us now. So what we can do is to find something more interesting!
Here is one, maybe. Assume that all the stars are so far from us that we can treat them as points in a plane. You are given N stars in the plane, and a number K (0≤K≤N). What you need to do is to find the minimum square covering at least K stars, whose edges are all parallel to the axis. The stars which are on the edges of the square are also covered.
The input will consist of multiple cases. Your program should process to the end of the input file.In the first line of one case, there are two integer N and K, 0<N≤1500, 0≤K≤N.
The next N lines are the description of the stars, one star per line. The ith line consists of two integers Xi and Yi, |Xi|<1000000, |Yi|<1000000.
The output will consist of one line for each case, in the format of “Case X: Y”, while X is the case number counting from 1, and Y is the edge length of the minimum square. X and Y are all integers.
Huge input, scanf is recommended.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<cmath>
#define rep(i,j,n) for(int i=j;i<n;i++)
#define repd(i,j,n) for(int i=j;i>n;i--)
#define N 1505
using namespace std;
struct node
{
int x,y;
} digt[N];
int indexx[N];
int indey[N];
int lx,ly;
int n,k;
int getx(int x)
{
return int(lower_bound(indexx,indexx+lx,x)-indexx);
}
int gety(int y)
{
return int(lower_bound(indey,indey+ly,y)-indey);
}
int dp[N][N];
void init()
{
memset(dp,0,sizeof(dp));
for(int i=0; i<n; i++)//将点对应到离散化后的平面上
{
int x1=getx(digt[i].x);
int y1=gety(digt[i].y);
dp[x1][y1]++;
}
for(int i=1; i<ly; i++)
dp[0][i]=dp[0][i-1]+dp[0][i];
for(int i=1; i<lx; i++)
dp[i][0]=dp[i-1][0]+dp[i][0];
for(int i=1; i<lx; i++)
for(int j=1; j<ly; j++)
dp[i][j]=dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+dp[i][j]; //dp[i][j]表示0,0到i,j矩阵中点的个数
}
int nextx[N],nexty[N];//nextx[i]表示x轴上离散化第i个点在加上实际Len的值后在离散化平面上的位置
bool solve(int len)
{
//--------------------------------------------------------
int t=0;
for(int i=0; i<lx; i++)
{
for(; t<lx; t++)
if(indexx[i]+len<indexx[t])break;
nextx[i]=t-1;
}
t=0;
for(int i=0; i<lx; i++)
{
for(; t<lx; t++)
if(indey[i]+len<indey[t])break;
nexty[i]=t-1;
}
//这里求出实际边长对应在离散化后的x,y的差,
//-----------------------------------------------------------
int x1,y1;
for(int i=0; i<lx; i++)
for(int j=0; j<ly; j++)
{
x1=nextx[i];
y1=nexty[j];
int ll=0,rr=0,lr=0;//分别表示这个矩阵的左边,右边,和左下面积上的点数目
if(i>0)ll=dp[i-1][y1];
if(j>0)rr=dp[x1][j-1];
if(i>0&&j>0)
lr=dp[i-1][j-1];
if(dp[x1][y1]-ll-rr+lr>=k)return true;
}
return false;
}
int main()
{
//freopen("test.txt","r",stdin);
int test=1;
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i=0; i<n; i++)
{
scanf("%d%d",&digt[i].x,&digt[i].y);
indexx[i]=digt[i].x;
indey[i]=digt[i].y;
}
sort(indexx,indexx+n); //对X轴离散化
sort(indey,indey+n);//对Y轴离散化
lx=unique(indexx,indexx+n)-indexx;
ly=unique(indey,indey+n)-indey;
init();//预处理
int l=0,r=2000005;
while(l<r)//二分枚举边长
{
int mid=(l+r)>>1;
if(solve(mid))r=mid;
else l=mid+1;
}
printf("Case %d: %d\n",test++,l);
}
return 0;
}
/**************************************************************
Problem: 2525
User: 11072215
Language: C++
Result: Accepted
Time:176 ms
Memory:10156 kb
****************************************************************/