洛谷P4835 摘果实

题面:https://www.luogu.com.cn/problem/P4835

题解:我们先将规划性问题转化为判定性问题:二分答案。
现在的问题是:如何check?
设当前二分的答案为\(T\),也就是说每个工人最多采摘\(T\)次。
考虑如何规划才能采完所有果子。
对于对数目\(w\)有限制的工人,若将他们按\(a[i]\)(限定数目)
排序,可以发现:\(a[i]\)越小,能摘的东西就越少。废话
而我们又想“人尽其用”,于是我们发现一种可行的贪心策略:
对于\(a[i]\)小的工人,让他们在能力范围内尽量摘\(h[i]\)大的
果子。
想想这么做为什么是正确的:对于\(h[i]\)越大的果子,能摘它的
b类工人越少,因此a类工人摘这些果子总是最优的。
整个过程可以用一个大根堆来实现。
代码:

#include
using namespace std;
#define re register int
#define F(x,y,z) for(re x=y;x<=z;x++)
#define FOR(x,y,z) for(re x=y;x>=z;x--)
typedef long long ll;
#define I inline void
#define IN inline int
templateI read(D &res){
    res=0;register D g=1;register char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')g=-1;
        ch=getchar();
    }
    while(isdigit(ch)){
        res=(res<<3)+(res<<1)+(ch^48);
        ch=getchar();
    }
    res*=g;
}
typedef pairpii;
struct P{
    int h,w,id;
}p[101000];
priority_queueq;
pii nd;
int n,m,A,B,a[50500],f[50500],b[50500],g[50500],vis[101000];
inline bool bb2(P x,P y){return x.h^y.h?x.h>1;
    if(ck(mid))y=mid;
    else x=mid+1;
    return divided(x,y);
}
int main(){
    read(A);read(B);read(n);
    F(i,1,A)read(a[i]);sort(a+1,a+1+A);
    F(i,1,B)read(b[i]);sort(b+1,b+1+B);
    F(i,1,n)read(p[i].w),read(p[i].h);
    sort(p+1,p+1+n,bb1);
    FOR(i,n,1){
        if(a[A]<=p[i].w&&b[B]<=p[i].h){
            cout<<"Impossible";
            return 0;
        }
    }
    m=A+B;
    if(n%m==0)m=n/m;
    else m=(n/m)+1;
    //system("pause");
    printf("%d",divided(m,n));
    return 0;
}

你可能感兴趣的:(洛谷P4835 摘果实)