标签:
【BZOJ 1 148】【CTSC 2008】挂缀
这题显然是个贪心,然而我们应该如何贪才能得到最优解= =。。。。
假设我们按重量升序贪心,那我们可以得到反例(假设在挂缀底部):设有i,j,j<i且W_j<W_i
那么当C_i<W_j,W_i<C_j时,应该选i而不是j
假设我们按拉力升序贪心,依旧可以得到反例(假设在挂缀顶部,S为链以下重量和):设有i,j,j<i,且C_j<C_i
那么当C_i<S+W_j,S+W_i<C_j时,应该先选i当第二高的,而非链顶
= =那如何贪心呢,观察以上两个式子,我们发现C_i+W_i<C_j+W_j,于是我们按$C+W$拍升序贪心。然而这样我们只保证了第一问,第二问需要我们维护原链中最大重量。贪心策略是,能挂到当前链顶就挂,不能挂重量看是否小于链中最大重量,小于则替换(由于排序的方法,替换的挂缀C值只能大于原位置C值,因此可替换),复杂度O(n log n)code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct hq{
long long wgt,f,sum;
bool operator <(hq const &a) const
{return sum<a.sum;}
}a[1000001];
int n;
long long nowwgt=0,nowl=0;
priority_queue<int> q;
int main()
{
int i;
scanf("%d",&n);
for (i=1;i<=n;++i)
{
scanf("%I64d%I64d",&a[i].f,&a[i].wgt);
a[i].sum=a[i].f+a[i].wgt;
}
sort(a+1,a+n+1);
for (i=1;i<=n;++i)
{
if (nowwgt<=a[i].f) {q.push(a[i].wgt); nowl++; nowwgt=nowwgt+a[i].wgt;}
else if (q.top()>a[i].wgt) {nowwgt=nowwgt-q.top()+a[i].wgt; q.pop(); q.push(a[i].wgt);}
}
printf("%lld\n%lld\n",nowl,nowwgt);
}版权声明:本文为博主原创文章,未经博主允许不得转载。
【BZOJ 1148】【CTSC 2008】挂缀【BZOJ 1 148】【CTSC 2008】挂缀
标签:
原文地址:http://blog.csdn.net/lcomyn/article/details/47110317