题目描述
又到吃饭时间,Polo 面对饭堂里琳(fei)琅(chang)满(keng)目(die)的各种食品,又陷入了痛苦的抉择中:该是吃手(jiao)打肉饼好呢,还是吃豆(cai)角(chong)肉片好呢?嗯……又不是天秤座怎么会酱紫呢?
具体来说,一顿饭由M 个不同的部分组成(荤菜,素菜,汤,甜品,饮料等等),Polo 要在每个部分中选一种作为今天的午饭。俗话说的好,永远没有免费的午餐,每种选择都需要有一定的花费。长者常常教导我们,便宜没好货,最便宜的选择估计比较坑爹,可囊中羞涩的Polo 还要把钱省下来给某人买生日礼物,这该怎么办呢?
于是一个折中方案出来了:第K 便宜的组合要花多少钱?这就要靠你了。
输入
第一行两个数M,K,含义如上所述。
接下来M 行,先是一个整数Ai,表示第i 个部分有多少种选择。接下来用空格分开的Ai 个整数表示每种选择的价格。
输出
一行一个整数表示答案。
样例输入
2 2
2 1 3
2 2 2
样例输出
3
提示
【样例解释】
最便宜的选择是第一部分选择1 块钱的,第二部分选择2 块的。但由于第二部分里2 块钱有两种不同的选择,所以第二便宜的总花费仍然是3 块。
此题跟poj2442是一样的,以前也做过,但考试的时候却一直想不出做法。今天又整理了一下。
首先要一行一行来,设运行到i行。
s[j]表示1−(i−1)行第j小的方案的花费。
然后对于每行,要初始化一些数,分别把第i小的和该行第1个加起来。
void prepare(int i)
{
tot=0;
len=0;
for(int j=1;j<=x;j++)
{
tot++;
heap[tot].l=j; //l表示它是s数组中第l小的
heap[tot].r=1; //r表示它在该行取了第r个
heap[tot].v=s[j]+a[i][1];
up(tot);
}
}
然后一直取最小的,(必须直接取,因为指针往后面移动的话显然更大)。然后那个最小的r指针+1,产生出一个新的数。
len++;
t[len]=heap[1].v;
if(heap[1].r+1<=a[i][0]) //r还能往后加1
{
tot++;
heap[tot].l=heap[1].l;
heap[tot].r=heap[1].r+1;
heap[tot].v=heap[1].v-a[i][heap[1].r]+a[i][heap[1].r+1];
}
这样的好处就是,你只需要考虑r这个下标,并且不影响取m个最小值的正确性。
#include
#include
#include
#include
#define ll long long
using namespace std;
int n,m,x,tot,len;
int a[11][500001];
ll s[100005],t[100005];
struct ty
{
int l,r;
ll v;
}heap[100005];
void up(int id)
{
while(id/2>=1)
{
if(heap[id].vid/2].v)
{
swap(heap[id],heap[id/2]);
id=id/2;
}
else break;
}
}
void down(int id)
{
while(id*2<=tot)
{
int j;
if(id*2+1>tot||heap[id*2].vid*2+1].v) j=id*2;
else j=id*2+1;
if(heap[id].v>heap[j].v)
{
swap(heap[id],heap[j]);
id=j;
}
else break;
}
}
void prepare(int i)
{
tot=0;
len=0;
for(int j=1;j<=x;j++)
{
tot++;
heap[tot].l=j;
heap[tot].r=1;
heap[tot].v=s[j]+a[i][1];
up(tot);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i][0]);
for(int j=1;j<=a[i][0];j++) scanf("%d",&a[i][j]);
sort(a[i]+1,a[i]+a[i][0]+1);
}
x=a[1][0];
for(int i=1;i<=x;i++) s[i]=a[1][i];
for(int i=2;i<=n;i++)
{
prepare(i);
while(1)
{
len++;
t[len]=heap[1].v;
if(heap[1].r+1<=a[i][0])
{
tot++;
heap[tot].l=heap[1].l;
heap[tot].r=heap[1].r+1;
heap[tot].v=heap[1].v-a[i][heap[1].r]+a[i][heap[1].r+1];
}
swap(heap[1],heap[tot]);
tot--;
down(1);
x=max(x,len);
if(len==m||tot==0) break;
}
for(int j=1;j<=x;j++) s[j]=t[j];
}
cout<return 0;
}