• 【BZOJ2034】最大收益(贪心)


    【BZOJ2034】最大收益(贪心)

    题面

    BZOJ

    题解

    首先显然让价值越大的占用一个时刻一定更优。
    所以把所有东西按照价值排序之后来处理,那么显然就是把前面的全部放好之后,考虑来放当前这个东西,如果能够放下那么就放,否则直接丢掉。
    考虑如何检查是否能下放。
    首先缩小区间的规模,对于每个位置,找到从他们的左端点开始,往右第一个未被标记的点标记,最后只有被标记的点才可能出现在匹配中。
    那么记录每个点的匹配位置,然后从左往右考虑所有可以的匹配位置,如果当前位置没有匹配,则直接匹配。
    否则如果当前位置匹配的东西的([l,r])(r)比这段区间的(r)大,则尝试能否匹配本来放的东西(因为它的(r)更大,更可能在后面找到一个匹配),如果不行则不行,否则则修改匹配有解。
    这样子最多检查(n)个元素的匹配,而只需要加入(n)次,所以复杂度(O(n^2))

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define MAX 5050
    inline int read()
    {
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
    }
    int n,p[MAX],book[MAX];ll ans;
    struct Node{int l,r,v,p;}a[MAX];
    bool cmpv(Node a,Node b){return a.v>b.v;}
    bool cmpl(Node a,Node b){return a.l<b.l;}
    bool check(int x,int pos)
    {
    if(p[pos]>a[x].r)return false;
    if(!book[pos]){book[pos]=x;return true;}
    if(a[book[pos]].r<=a[x].r)return check(x,pos+1);
    else if(check(book[pos],pos+1)){book[pos]=x;return true;}
    return false;
    }
    int main()
    {
    n=read();
    for(int i=1;i<=n;++i)a[i].l=read(),a[i].r=read(),a[i].v=read();
    sort(&a[1],&a[n+1],cmpl);
    for(int i=1;i<=n;++i)p[i]=max(p[i-1]+1,a[i].l);
    a[1].p=1;
    for(int i=2;i<=n;++i)
    {
    	a[i].p=a[i-1].p;
    	while(p[a[i].p]<a[i].l&&a[i].p<n)++a[i].p;
    }
    sort(&a[1],&a[n+1],cmpv);
    for(int i=1;i<=n;++i)if(check(i,a[i].p))ans+=a[i].v;
    printf("%lld
    ",ans);
    return 0;
    }
    
  • 相关阅读:
    大公司?小公司?
    git 学习笔记
    django学习笔记
    web servieces 学习小栗子
    python列表推导式
    什么叫事务,事务的特性
    监听问题汇总
    oracle数据库导入导出
    ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务--解决办法(转)
    目标修正
  • 原文地址:https://www.cnblogs.com/cjyyb/p/10574980.html
Copyright © 2020-2023  润新知