Codeforces Gym - 101234G Dreamoon and NightMarket

G. Dreamoon and NightMarket

time limit per test
1 second
memory limit per test
512 mebibytes
input
standard input
output
standard output

After moving to Taipei, Dreamoon always goes to dinner at Jinmei Night Market. There are N kinds of food sold at Jinmei Night Market. These foods are numbered from 1 to N. The price of one piece of i-th food is pi.

Every night, Dreamoon will choose a non-empty set of foods and eat one piece of each food in this set. Dreamoon likes new things. So he won't choose the same set in two different nights. Besides this, because Dreamoon is a poor boy, each night, he will choose the cheapest food set that he didn't choose before.

Now, you are given a positive integer K. Can you tell Dreamoon which set of foods he will choose on K-th day? You only have to tell him how much he will spent on this day.

Input

The input consists of two lines. The first line contains an integer N. The second line consists of N integers p1, p2, ..., pN.

  • 2 ≤ N ≤ 2 × 105
  • 1 ≤ K ≤ min(106, 2N - 1)
  • 1 ≤ pi ≤ 108
Output

Output one number indicating how much Dreamoon will spend on food on K-th day.

Examples
input
5 30
4 2 1 16 8
output
30
input
4 5
1 1 2 2
output
2



在序列中随便选数构成集合,输出集合中数的和第k小的和。


用类似DP的思想,用之前的和生成后续的和。

对于一个数,只有选和不选两种可能。

用优先队列维护所有可能的和。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <queue>
#include <algorithm>
#define mem0(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=200005,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
ll a[maxn],b[maxn*5];
struct node {
	ll id,dist;
	node(ll id,ll dist):id(id),dist(dist) {}
	bool operator <(const node &x)const {
	    return dist>x.dist || (dist==x.dist&&id>x.id);
	}
};
priority_queue<node> pq;

int main() {
	int i,n,k,id;
	scanf("%d%d",&n,&k);
	for (i=1;i<=n;i++) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	pq.push(node(1,a[1]));
	for (i=1;i<=k;i++) {
		b[i]=pq.top().dist;
		id=pq.top().id;
		if (id<n) {
			pq.push(node(id+1,b[i]-a[id]+a[id+1]));
			pq.push(node(id+1,b[i]+a[id+1]));
		}
		pq.pop();
	}
	printf("%lld\n",b[k]);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值