码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj 2034 [2009国家集训队]最大收益

时间:2017-10-03 11:27:21      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:alt   分享   strong   line   sizeof   efi   isp   sed   lap   

这个题,我想的是用一些神奇的线段树做法,根本没想匹配

但是好像很显然啊

(论文写的也太长了...)

给的l,r范围很大,其实有用的只有n个时刻

那可以先离散一下

然后把 各个线段按照权值从大到小排序,一个一个选

有矛盾一定选择权值大的,所以前面选定的集合一定是最优的

然后自己论文里说的check函数,看有没有空余的时刻,有就加上,没有就跳过

 

 

技术分享
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=7006;

struct son
{
    int l,r,v,s;
}ji[N];
bool ok_l(son a,son b)
{
    if(a.l==b.l)
        return a.r<b.r;
    return a.l<b.l;
}
bool ok_v(son a,son b)
{
    return a.v>b.v;
}

int n;
int pos[N];// 存离散后的点
int match[N];// 第i个活跃点选的任务

bool fin(int x,int t)
{
    if(pos[t]>ji[x].r)
        return 0;
    if(match[t]==-1)
    {
        match[t]=x;
        return 1;
    }
    int tt=match[t];
    if(ji[x].r>ji[tt].r)// 贪心
        return fin(x,t+1);
    else
        if(fin(tt,t+1))
        {
            match[t]=x;
            return 1;
        }
    return 0;
}

int main(){

    //freopen("in.in","r",stdin);

    mem(match,-1);

    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d%d%d",&ji[i].l,&ji[i].r,&ji[i].v);
    sort(ji+1,ji+1+n,ok_l);
    pos[0]=0;
    for(int i=1;i<=n;++i)
        pos[i]=max(pos[i-1]+1,ji[i].l);

    ji[1].s=1;
    for(int i=2;i<=n;++i)
    {
        ji[i].s=ji[i-1].s;
        while( pos[ji[i].s]<ji[i].l&&ji[i].s<n )++ji[i].s;
    }

    sort(ji+1,ji+1+n,ok_v);
    ll ans=0;
    for(int i=1;i<=n;++i)
        if(fin(i,ji[i].s))
            ans+=ji[i].v;
    cout<<ans;
}
23333

 

bzoj 2034 [2009国家集训队]最大收益

标签:alt   分享   strong   line   sizeof   efi   isp   sed   lap   

原文地址:http://www.cnblogs.com/A-LEAF/p/7623378.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!