4345: [POI2016]Korale
Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 316 Solved: 117
[ Submit][ Status][ Discuss]
Description
有n个带标号的珠子,第i个珠子的价值为a[i]。现在你可以选择若干个珠子组成项链(也可以一个都不选),项链的价值为所有珠子的价值和。现在给所有可能的项链排序,先按权值从小到大排序,对于权值相同的,根据所用珠子集合的标号的字典序从小到大排序。请输出第k小的项链的价值,以及所用的珠子集合。
Input
第一行包含两个正整数n,k(1<=n<=1000000,1<=k<=min(2^n,1000000))。
第二行包含n个正整数,依次表示每个珠子的价值a[i](1<=a[i]<=10^9)。
Output
第一行输出第k小的项链的价值。
第二行按标号从小到大依次输出该项链里每个珠子的标号。
Sample Input
4 10
3 7 4 3
3 7 4 3
Sample Output
10
1 3 4
1 3 4
HINT
Source
先考虑第一问
将所有珠子按照价值升序排好,维护一个堆
堆中存放若干二元组(x,y),表示当前项链价值为x,最后一颗珠子是y
每次取出堆顶元素,计入答案,然后对于当前项链,选择新增下一颗珠子或是舍去最后一颗珠子并放入后一颗
这样重复k次就能得到第一问的答案了
第二问直接暴力搜索就行了
在用堆统计第一问答案时顺便记录权值和答案相同的项链的数量
每次贪心地选择编号最小的可以继续添加的珠子,即加入这颗珠子后项链的价值仍然不超过第一问答案
由于每新增一颗珠子就新增了一条项链,而有效项链条数是不超过k的
所以这样的搜索很快就能结束,查询下一颗珠子的工作可以交由线段树解决
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#define min(a,b) ((a) < (b) ? (a) : (b))
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int T = 4;
const int maxn = 1E6 + 10;
typedef long long LL;
struct data{
LL sum; int pos; data(){}
data(LL sum,int pos): sum(sum),pos(pos){}
bool operator < (const data &B) const {return sum > B.sum;}
};
int n,m,res,stk[maxn],A[maxn],B[maxn],Min[maxn*T];
LL Ans;
priority_queue <data> Q;
inline void Build(int o,int l,int r)
{
if (l == r) {Min[o] = A[l]; return;}
int mid = l + r >> 1;
Build(o<<1,l,mid); Build(o<<1|1,mid+1,r);
Min[o] = min(Min[o<<1],Min[o<<1|1]);
}
inline int Query(int o,int l,int r,int pos,LL now)
{
if (Min[o] > now) return maxn;
if (l == r) return l; int mid = l + r >> 1;
if (pos > mid) return Query(o<<1|1,mid+1,r,pos,now);
int ret = Query(o<<1,l,mid,pos,now);
return ret == maxn ? Query(o<<1|1,mid+1,r,pos,now) : ret;
}
inline void Dfs(LL sum,int tp,int pos)
{
if (sum == Ans)
{
if (res == 1)
{
for (int i = 1; i <= tp; i++) printf("%d ",stk[i]);
exit(0);
}
--res; return;
}
LL now = Ans - sum;
for (int Nex = pos + 1; Nex <= n;)
{
int ret = Query(1,1,n,Nex,now);
if (ret == maxn) return; stk[tp + 1] = ret;
Dfs(sum + 1LL * A[ret],tp + 1,ret); Nex = ret + 1;
}
}
inline int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret * 10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
n = getint(); m = getint();
for (int i = 1; i <= n; i++) A[i] = B[i] = getint();
sort(B + 1,B + n + 1); Q.push(data(B[1],1));
for (int i = 1; i < m; i++)
{
data k = Q.top(); Q.pop();
if (k.sum == Ans) ++res; else Ans = k.sum,res = 1;
if (k.pos == n) continue;
Q.push(data(k.sum + 1LL * B[k.pos + 1],k.pos + 1));
Q.push(data(k.sum + 1LL * (B[k.pos + 1] - B[k.pos]),k.pos + 1));
}
cout << Ans << endl;
Build(1,1,n); Dfs(0,0,0);
return 0;
}