题意:给一个整数序列,长度为n,求在这个序列的子序列中和为第m大的数。
分析:
设置优先级队列
{
sum: 当前和
next: 加入下个元素的和
ith: 将要考虑的下个元素
}
以next为优先级,小的先出队
读入数据后排序,初始化队列第一个元素(0,a[0],0)
每次出队一个元素,入队(sum,sum+a[ith],ith+1),(next,next+a[ith],ith+1),即是否加上a[ith]都考虑进去了。
这样每次新加入的元素都是下一个最小的(next),进行m次就得到了第m小。
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <queue>
using namespace std;
const int N=100011;
int a[N];
int n,m;
struct Node
{
int sum;
int next;
int ith;
Node(){};
Node(int _sum,int _next,int _ith)
{
sum=_sum;
next=_next;
ith=_ith;
}
bool operator < (const Node &b) const
{
return b.next<next;
}
};
int Solve(int m)
{
priority_queue<Node> Q;
Node tmp;
tmp.sum=0;
tmp.next=a[0];
tmp.ith=0;
Q.push(tmp);
int cnt=0;
a[n]=0;
while(cnt<m)
{
tmp=Q.top();
Q.pop();
if(tmp.ith>=n) continue;
Q.push(Node(tmp.sum,tmp.sum+a[tmp.ith+1],tmp.ith+1));
Q.push(Node(tmp.next,tmp.next+a[tmp.ith+1],tmp.ith+1));
cnt++;
}
for(m=0;!Q.empty();m++)
{
a[m]=Q.top().sum;
Q.pop();
}
sort(a,a+m);
return a[m-1];
}
int main()
{
int t,i,tt=1;
cin>>t;
while(t--)
{
cin>>n>>m;
for(i=0;i<n;i++)
cin>>a[i];
sort(a,a+n);
printf("Case #%d: %d\n",tt++,Solve(m));
}
return 0;
}
标签:tmp,Node,优先,ith,队列,sum,next,int,HDU4546 From: https://blog.51cto.com/u_16146153/6388679