题意:
给你n个人,问最大可以选多少人,使题目给出的不等式成立
题解:
1. 先把所有点按A*h+B*v从小到大排序
2. 枚举最小高度minH
3. 从左到右枚举minV,每次minV+1转移时,将原答案集合中的在左边界上的点删除,然后把点向后扫描,把能加入的点加入集合。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long LL; LL read() { LL a=0;char ch=getchar(); while(ch<'0'||ch>'9')ch=getchar(); a=a*10+ch-'0'; ch=getchar(); while(ch>='0'&&ch<='9') { a=a*10+ch-'0'; ch=getchar(); } return a; } const int maxn=5009; const double eps=1e-8; struct point { LL x,y; bool operator<(const point &a) const {return x+y<a.x+a.y;} } p[maxn],u,v; LL x[maxn],low,high; int n,N,A,B,C,ans,best=0,remain; priority_queue<point> Q; bool cmp(point a, point b) { return a.x<b.x; } void del() { N=1; for (int i=2;i<=n;i++) if (x[i]!=x[i-1])x[++N]=x[i]; } int main() { freopen("team.in","r",stdin); freopen("team.out","w",stdout); remain=n=read();A=read();B=read();C=read(); for (int i=1;i<=n;i++) { p[i].x=read()*A; x[i]=p[i].y=read()*B; } sort(x+1,x+n+1); del(); sort(p+1,p+n+1,cmp); for (int i=1;i<=N;i++) { while (!Q.empty())Q.pop(); ans=0;low=x[i];high=x[i]+C; for (int j=n;j;j--) { if (low <= p[j].y && p[j].y <= high) { u=p[j]; Q.push(u); ans++; if (low==p[j].y)remain--; } while (!Q.empty()) { v=Q.top(); if (v.x+v.y<=high+p[j].x)break; Q.pop(); ans--; } best=max(best,ans); } if (remain<=best) break; } printf("%d\n",best); return 0; }