bzoj 2034 [2009国家集训队]最大收益
Posted A_LEAF
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2034 [2009国家集训队]最大收益相关的知识,希望对你有一定的参考价值。
这个题,我想的是用一些神奇的线段树做法,根本没想匹配
但是好像很显然啊
(论文写的也太长了...)
给的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; }
以上是关于bzoj 2034 [2009国家集训队]最大收益的主要内容,如果未能解决你的问题,请参考以下文章