题意:

给你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;
}

 

posted on 2018-02-14 10:20  宣毅鸣  阅读(117)  评论(0编辑  收藏  举报