洛谷 2887 USACO2007NOV 防晒霜Sunscreen 题解

题意简述

C C C个奶牛晒太阳,但是第 i i i个奶牛有一个要求,就是阳光值必须在 [ l i , r i ] [l_i,r_i] [li,ri]之间,才能享受晒太阳。阳光强度开始都是 ∞ \infin 。有 S S S种防晒霜,第 i i i种珂以让一个奶牛收到的阳光保持在 t i t_i ti,数量有 c i c_i ci个。每个奶牛只能涂一种防晒霜,求最多多少奶牛能享受晒太阳。

数据

输入

第一行两个正整数 C , S C,S C,S,如题。
接下来 C C C行每行两个正整数,第 i i i行是 l i l_i li r i r_i ri
再接下来 S S S行每行两个正整数,第 i i i行是 t i t_i ti, c i c_i ci

输出

如题。输出最多多少奶牛能够晒到日光浴。

样例

输入
3 2
3 10
2 5
1 5
6 2
4 1
输出
2

思路

看到标签写着“蒟阵乘法”,"网络流"什么的把我吓的半死。。。
仔细想想,好像贪心就珂以了。
防晒霜的 t i t_i ti肯定是要排序,和奶牛的区间肯定要排序,要不然没处入手。奶牛的区间很明显是按 r r r升序排序。如果我们有一个十分优秀的排序防晒霜的方法,那么我们只要 O ( C ) O(C) O(C)枚举一个牛, O ( S ) O(S) O(S)枚举防晒霜,找到第一个就退出,就一定是最优解了。总复杂度 O ( C S ) O(CS) O(CS)直接过来。

那么, t i t_i ti是升序 or 降序?(一脸懵逼。。。

直觉想想,升序好像是对的。实际上,USACO是珂以看到实时成绩的,用升序AC了,用降序只过了样例。但是我们证明,或者意会明白:为什么一定要升序?

有点像刘汝佳小蓝书上的第一题:Dragon of Loowater,假设现在我们降序排序,如果我们有一个防晒霜的 t t t值很大,但是我们把它给了一个 r r r很小的奶牛,那么,后面 r r r更大的奶牛就缺少了选择的余地,十分不划算。更划算的方法应该是 t t t值相对小防晒霜的配 r r r值也相对小的防晒霜, t t t值相对大的防晒霜配 r r r值也相对大的奶牛,才对。

但是这个题和Dragon of Loowater不一样的地方在于,对于每一个奶牛,因为是一段区间,所以选择的防晒霜编号不一定单调不减,所以要每一次都重新枚举, O ( C S ) O(CS) O(CS)的。

代码:

#include
using namespace std;
namespace Flandle_Scarlet
{
    #define N 2600
    struct cow
    {
        int l,r;
    }C[N];bool operator<(cow a,cow b) {return a.r<b.r;}
    struct SPF
    {
        int c,t;
    }S[N];bool operator<(SPF a,SPF b) {return a.t<b.t;}
    int c,s;
    void Input()
    {
        scanf("%d%d",&c,&s);
        for(int i=1;i<=c;++i)
        {
            scanf("%d%d",&C[i].l,&C[i].r);
        }
        for(int i=1;i<=s;++i)
        {
            scanf("%d%d",&S[i].t,&S[i].c);
        }
        sort(C+1,C+c+1);
        sort(S+1,S+s+1);
    }

    void Solve()
    {
        int ans=0;
        for(int i=1;i<=c;++i)
        {
            for(int j=1;j<=s;++j)
            {
                if (S[j].t>=C[i].l and S[j].t<=C[i].r and S[j].c)
                {
                    --S[j].c;
                    ++ans;
                    break;
                }
            }
        }
        printf("%d\n",ans);
    }

    void Main()
    {
        if (0)
        {
            freopen("","r",stdin);
            freopen("","w",stdout);
        }
        Input();
        Solve();
    }
};
main()
{
    Flandle_Scarlet::Main();
    return 0;
}

回到总题解界面

你可能感兴趣的:(洛谷,题解)