[SCOI2007]组队

[SCOI2007]组队

题面

Luogu

题解

题意要求求出当以一个H和一个V为最小值的时候,满足A*(H-minH)+B *(V-minV)<=C的个数

显然最简单的做法是枚举出minH和minV的值,在循环一遍找那些符合,然而这种做法并不适用于5000的数据

考虑讲时间复杂度优化到O(N2

注意到当MinH一定时,此时任意一个H>minH ,有V<=C/B + minV 

代码

#include<bits/stdc++.h>

using namespace std;

inline int read()
{
    int f=1,x=0;
    char ch;
    do
    {
        ch=getchar();
        if(ch=='-') f=-1;
    }while(ch<'0'||ch>'9');
    do
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }while(ch>='0'&&ch<='9');
    return f*x;
}

struct Player
{
    long long v;
    long long h;
    long long s;
};

long long n,a,b,c;
Player p[5000 + 10],p2[5000 + 10];
long long ans;

inline bool cmp1(Player a,Player b)
{
    return a.h<b.h;
}

inline bool cmp2(Player a,Player b)
{
    return a.s<b.s;
}

int main()
{
    n=read();a=read();b=read();c=read();
    for(int i=1;i<=n;i++)
    {
        p[i].h=read();
        p[i].v=read();
        p[i].s=p[i].h*a+p[i].v*b;
        p2[i]=p[i];
    }
    sort(p+1,p+n+1,cmp1);
    sort(p2+1,p2+n+1,cmp2);
    for(int i=1;i<=n;i++)
    {
        long long l=0,r=0;long long cnt=0;
        long long MAXI = c/b+p[i].v;
        for(int j=1;j<=n;j++)
        {
            while(r<n&&p2[r+1].s<=c+a*p[j].h+b*p[i].v)
            {
                if(p[i].v<=p2[++r].v&&p2[r].v<=MAXI)
                {
                    cnt++;
                }
            }
            while(l<n&&p[l+1].h<p[j].h)
            {
                if(p[i].v<=p[++l].v&&p[l].v<=MAXI)
                {
                    cnt--;
                }
            }
            ans=max(ans,cnt);
        }
        
    }
    cout<<ans<<endl;
}
原文地址:https://www.cnblogs.com/wlzs1432/p/11136077.html