• 【BZOJ】1707: [Usaco2007 Nov]tanning分配防晒霜


    【算法】贪心扫描线(+堆)

    【题意】给定n头牛有区间[a,b],m个防晒霜值为ai,每个可以使用bi次,每次可以使包含它的区间涂到防晒霜,问最多被涂牛数。

    【题解】

    参考:[bzoj1707]: [Usaco2007 Nov]tanning分配防晒霜 by czllgzmzl

    本题同样是区间和点的贪心,可以参考另一道题【BZOJ】1828: [Usaco2010 Mar]balloc 农场分配(经典贪心)

    区间和点的贪心有两种经典做法,本题一样。

    一、从区间角度出发,按区间右端点排序

    区间第二关键字按左端点从小到大排序,防晒霜排序后,对于每个区间选择其最左的防晒霜。

    这个过程可以用二分+并查集实现,参考上帝造题2。

    二、从点的角度出发,按区间左端点排序

    对于每个防晒霜,对左影响一致(左边的能用都用了)的情况下,给右端点最小的。

    用堆实现。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<cctype>
    using namespace std;
    const int maxn=2510;
    priority_queue<int,vector<int>,greater<int> >q;
    int n,m;
    struct interval{int x,y;}b[maxn];
    struct point{int x,c;}a[maxn];
    bool cmp(interval a,interval b){return a.x<b.x;}
    bool cmp2(point a,point b){return a.x<b.x;}
    
    int read()
    {
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    int main(){
        m=read();n=read();
        for(int i=1;i<=m;i++)b[i].x=read(),b[i].y=read();
        for(int i=1;i<=n;i++)a[i].x=read(),a[i].c=read();
        sort(b+1,b+m+1,cmp);
        sort(a+1,a+n+1,cmp2);
        int now=0,ans=0;
        for(int i=1;i<=n;i++){
            while(now<m&&b[now+1].x<=a[i].x)now++,q.push(b[now].y);
            for(int j=1;j<=a[i].c;j++){
                while(!q.empty()&&q.top()<a[i].x)q.pop();
                if(q.empty())break;
                ans++;q.pop();
            }
        }
        printf("%d",ans);
        return 0;
    }        
    View Code
  • 相关阅读:
    [LuoGu] P1004 方格取数
    [LuoGu] P1018 乘积最大
    [LuoGu] P2758 编辑距离
    [JZOJ] 01知多少
    [LuoGu] P1731 生日蛋糕
    $mathcal{Const,Inline,Register}$用法总结
    T2027 蜈蚣
    T57274 黑暗城堡
    P2312 解方程
    AT2412 最大の和
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7577389.html
Copyright © 2020-2023  润新知