http://codeforces.com/problemset/problem/994/B
题目很容易理解,就是有n个骑士,他们都有自己的战斗值,而且每个人的身上都有一定的硬币,每个骑士是可以杀掉战斗值比自己小的骑士并能够得到他的硬币,但是每个骑士不能杀超过k个人,求每个骑士可以获得的最大钱数。
这道题是一道贪心题,开始我以为,局部最优,开始将所有的骑士的硬币数从大到小的顺序排一遍,然后每次都从最大硬币持有者开始遍历一遍,两层for循环,但是w了,不知道为什么,但是这道题目的n太大,就算是不W也会TLE,所以靠改变,用multiset或者优先队列(但优先队列不好遍历),来做,首先要将这些骑士的战斗值从小到大sort一下,然后将后n-k+1个人放进容器里(priority_queue或者multiset),为什么是n-k+1,下面会解释。
我们是将所有的战斗值从小到大排序的,因此第i个人一定能打败前i个人,这里是不会打败人数超过k个,这里就要解释一下为什么是n-k+1个人放入容器里,因为第k+1个人是没有选择能力去杀战斗值比自己大的人,所以第k+1个人只能杀掉前k个,不管所得硬币或多或少,然后剩下的n-k+1个人就可以有选择的找硬币多的人,然后击败他(容器是一个从小到大排硬币的数量的),得到自己可以获得的最多硬币。
#include<bits/stdc++.h>
using namespace std;
int n,m,w;
const int maxn =15;
typedef long long ll;
struct node
{
ll c;
int id;
ll victem;
bool operator < (const node &a)const
{
return victem<a.victem;
}
}num[100005];
bool cmp1(node a,node b)
{
return a.victem>b.victem;
}
bool cmp2(node a,node b)
{
return a.id<b.id;
}
multiset <int> ms;
multiset <int> ::iterator it;
ll ans[100005];
ll num1[100005];
int main()
{
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>num[i].victem,num[i].id=i;
for(int i=1;i<=n;i++)
cin>>num[i].c;
sort(num+1,num+n+1);
k++;
for(int i=1;i<=n;i++)
{
if(i<=k)
num1[i]+=num1[i-1]+num[i].c,ms.insert(num[i].c);
else
{
ms.erase(ms.begin());//multiset里面始终有三个值,去掉最小的一个,然后
num1[i]=num[i].c;//加上身下的不就是能够得到的最大值吗
for(it=ms.begin();it!=ms.end();it++)
num1[i]+=*it;
ms.insert(num[i].c);
}
ans[num[i].id]=num1[i];
}
for(int i=1;i<=n;i++)
cout<<ans[i]<<" ";
cout<<endl;
return 0;
}