Live Archive 3695 Distant Galaxy

题意:给你平面上的n个点,找到一个矩形使得边界上包含尽量多的点,并输出最多的点数

我们分析后可以发现除非所有的输入点都在同一行/列上,最优矩阵的4条边都至少有一个点,因此我们可以枚举四条边界所穿过的点,然后统计点数,O(n^5)

可以考虑部分枚举,即只枚举矩阵的上下边界,用其他方法确定左右边界

对于一个竖线i,我们用l[i]表示竖线左边位于上下边界的点数(但是不算位于这条线上的点)

on[i]表示竖线上位于上下边界之间的点数(不统计位于上下边界的点)

on2[i]表示竖线上位于上下边界之间的点数(要统计位于上下边界的点)

所以给定左右边界i,j时,矩形上点数为l[j]-l[i]+on[i]+on2[j],当右边界j一定时,应当维护on[i]-l[i]的最大值

枚举完上下边界后,我们先从左到右扫描所有点计算l[i],on[i],on2[i].然后枚举右边界j同时维护on[i]-l[i](i<j)的max,顺便更新答案就解决了

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=105,inf=1e9;
inline void _read(int &x){
    char t=getchar();bool sign=true;
    while(t<'0'||t>'9')
    {if(t=='-')sign=false;t=getchar();}
    for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';
    if(!sign)x=-x;
}
struct wk{
	int x,y;
	bool operator < (const wk& a)const{
		return x<a.x;
	} 
}p[maxn];
int n,m,y[maxn],l[maxn],on[maxn],on2[maxn];
int main(){
	int cases=0,i,j,up,down;
	while(scanf("%d",&n)&&n){
		bool flag=1;
		for(i=1;i<=n;i++){
			_read(p[i].x);_read(p[i].y);
			y[i]=p[i].y;
		}
		sort(p+1,p+1+n);
		sort(y+1,y+1+n);
		int num=unique(y+1,y+1+n)-y;//删除所有高度相同的点
		num--;
		if(num<=2){
		    printf("Case %d: %d\n",++cases,n);	//只有两种以下的高度,可以用一个矩形覆盖所有点
		    continue;
		}
		int ans=0;
		for(down=1;down<=num&&flag;down++)
			for(up=down+1;up<=num;up++){
		    	int k=0;
		    	for(i=1;i<=n;i++){
		    		if(i==0||p[i].x!=p[i-1].x){
		    			on[++k]=on2[k]=0;
		    			l[k]=l[k-1]-on[k-1]+on2[k-1];
					}
					if(p[i].y>y[down]&&p[i].y<y[up])on[k]++;
					if(p[i].y>=y[down]&&p[i].y<=y[up])on2[k]++;
				}
				if(k<=2){
					printf("Case %d: %d\n",++cases,n);//道理同上
					flag=0;
				}
				if(!flag)break;
				int maxx=0;
				for(i=1;i<=k;i++){//注意下面的赋值顺序
					ans=max(ans,l[i]+on2[i]+maxx);
					maxx=max(maxx,on[i]-l[i]);
				}
			}
		if(flag)printf("Case %d: %d\n",++cases,ans);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值