Distant Galaxy
You are observing a distant galaxy using a telescope above the Astronomy Tower, and you think that a rectangle drawn in that galaxy whose edges are parallel to coordinate axes and contain maximum star systems on its edges has a great deal to do with the mysteries of universe. However you do not have the laptop with you, thus you have written the coordinates of all star systems down on a piece of paper and decide to work out the result later. Can you finish this task?
Input
There are multiple test cases in the input file. Each test case starts with one integer N , (1<=N<=100) , the number of star systems on the telescope. N lines follow, each line consists of two integers: the X and Ycoordinates of the K -th planet system. The absolute value of any coordinate is no more than 109 , and you can assume that the planets are arbitrarily distributed in the universe.
N = 0 indicates the end of input file and should not be processed by your program.
Output
For each test case, output the maximum value you have found on a single line in the format as indicated in the sample output.
Sample Input
10
2 3
9 2
7 4
3 4
5 7
1 5
10 4
10 6
11 4
4 6
0
Sample Output
Case 1: 7
这道题十分经典,它融合了多种思想,我们想到,对于1<=n<=100来说,要想求得答案,最简单粗暴的方法就是枚举上下边界,枚举左右边界,然后计算边界上一共有多少点,很显然,不管是以点为基准枚举(O(N^5))还是以坐标为基准枚举(以坐标显然不可行,坐标的范围在[-10^9,10^9]之间),都是低效的。
一拿到这个题应该思考的是他肯定是扫描没错了,做了这么多扫描的题,我发现了一个很统一的规律,只要是暴力无法求解的,那么一定存在一种策略,当枚举某一边界值时,另一边界值一定是有办法通过预处理或者状态维护找出一种可以在常量时间内求出结果来的方法,很类似的,这道题同Subsequece和Open Credit System有异曲同工之妙。
对于此题,我们将我们要枚举的上下界放在无穷远处,那么他就变成了一条直线,这个时候我们不就是求一个子区间使得他的至最大吗?那么求子区间的过程就是是求左右界的过程,而点的个数必定是正数,所以我们可以利用前缀和预处理一下前缀和,然后直接利用它单调的性质,类似Subsequence可以在线性的时间内求出答案。
现在做的无非就是如何将两条线处理成一条线,很简单,将两条线处于第i点左侧的点全部加进一个数组left内。同时维护一个on数组,不含上下边界点的右边界的点的数量;一个on2数组,包含上下边界点的右边界的点的数量。
其余的工作类似Subsequece和Open Credit System,请各位充分把握着两道题之后再仔细研究这道题的精髓所在。
另外还有使用离散化各种方法解决的,我认为太麻烦,不是这道题真正考察的精髓,不过日后会通过敲敲离散化这种类型的练习一下代码能力。
另外此题还是用了unique函数,他是将一个数列中的不同值按顺序排列在数列前端,并返回序列尾指针。
附代码如下:
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN (100+5)
struct POINT{
int x,y;
bool operator < (const POINT& var) const {return x<var.x;}
};
POINT P[MAXN];
int y[MAXN],on[MAXN],on2[MAXN],left[MAXN];
int n;
int solve(){
sort(P,P+n);
sort(y,y+n);
int m=unique(y,y+n)-y;
if(m<=2)return n;
int ans=0;
for(int D=0;D<n;D++){
for(int U=D+1;U<n;U++){
int yu=y[U],yd=y[D];
int line=0;
left[line]=0;on[line]=0;on2[line]=0;
if(yd<P[0].y&&P[0].y<yu)on[line]++;
if(yd<=P[0].y&&P[0].y<=yu)on2[line]++;
for(int i=1;i<n;i++){
if(P[i].x!=P[i-1].x){
line++;
on[line]=0;on2[line]=0;
left[line]=left[line-1]+on2[line-1]-on[line-1];
}
if(yd<P[i].y&&P[i].y<yu)on[line]++;
if(yd<=P[i].y&&P[i].y<=yu)on2[line]++;
}
if(line<=2)return n;
int x=0;
for(int i=0;i<n;i++){
ans=max(ans,left[i]+on2[i]+x);
x=max(x,on[i]-left[i]);
}
}
}
return ans;
}
int main(){
//freopen("in.txt","r",stdin);
int k=0;
while(scanf("%d",&n)==1&&n){
for(int i=0;i<n;i++){
scanf("%d%d",&P[i].x,&P[i].y);
y[i]=P[i].y;
}
printf("Case %d: %d\n",++k,solve());
}
//fclose(stdin);
return 0;
}