#include<bits/stdc++.h> #define debu using namespace std; const int maxn=100+50; struct point { int x,y; bool operator < (const point& rhs) const { if(rhs.y==y) return rhs.x>x; else return rhs.y>y; } }; int x[maxn]; int lt[maxn]; int bd1[maxn]; int bd2[maxn]; point g[maxn]; int cas=0,n,ans; int solve() { ans=0; sort(g,g+n); sort(x,x+n); int num=unique(x,x+n)-x; if(num<=2) return n; for(int i=0; i<num; i++) for(int j=i+1; j<num; j++) { int tot=0; int up=x[j]; int down=x[i]; memset(lt,0,sizeof(lt)); memset(bd1,0,sizeof(bd1)); memset(bd2,0,sizeof(bd2)); for(int k=0; k<n; k++) { if((!k)||g[k].y!=g[k-1].y) { tot++; lt[tot]=lt[tot-1]+bd2[tot-1]-bd1[tot-1]; } if(g[k].x<up&&g[k].x>down) bd1[tot]++; if(g[k].x<=up&&g[k].x>=down) bd2[tot]++; } if(tot<=2) return n; int tmp=0; for(int w=1; w<=tot; w++) { ans=max(ans,lt[w]+bd2[w]+tmp); tmp=max(tmp,bd1[w]-lt[w]); } } return ans; } int main() { #ifdef debug freopen("in.in","r",stdin); #endif // debug while(scanf("%d",&n)==1&&n) { for(int i=0; i<n; i++) { scanf("%d%d",&g[i].x,&g[i].y); x[i]=g[i].x; } printf("Case %d: %d\n",++cas,solve()); } return 0; }
题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1696
题解:枚举上下边界:up,down。枚举竖线i到j。lt[i]表示位于竖线i左侧上下边界上的点数,bd1[i]表示位于竖线i上且不包括上下边界的点数,bd2[i]表示位于竖线i上且包括上下边界的点数。则该枚举边界中的点数为lt[j]-lt[i]+bd1[i]+bd2[j],即固定j使得bd1[i]-lt[i]最大(可只枚举j,maxx=max(maxx,bd1[i]-lt[i]),maxx晚于j更新。特例:当x或y坐标不超过两个时,答案为n。