At297 E - Kth Takoyaki Set

E - Kth Takoyaki Set


原题链接

题意简述

给定一个长为n的可重序列a,定义\(f\)值为\(x_1·a_1+x_2·a_2+.....x_n·y_n\),其中\(x_1,x_2......x_n\)满足所有数都是非负整数,并且至少有一项是正数。求第k大的\(f\)值是多少?

思路简述

这题第k大很容易想到维护一个堆或者优先队列进行贪心操作
具体操作如下,有点类似bfs和dij的操作
1.将 \(a\) 数组进行排序去重然后维护一个以 \(a\) 的值和下标映射的pair添加到优先队列Q里。
2.取出优先队列中队头元素(这一定是当前遍历到的最小元素),遍历a数组中每个大于等于当前数的数字,将队头元素和这些数字相加推进优先队列。
3.如果当前趟和上一次对头元素相同,那么就可以跳过当前元素,每一趟操作保证一定找到当前未遍历到的最小值加入了优先队列
4.可以证明这样加进去的数字一定满足按从小到大的顺序并且把所有的值都遍历到。

AC code

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const ll inf=1e18;
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    priority_queue<pair<ll,int> ,vector<pair<ll,int> >,greater<pair<ll,int> > >Q;
    int n,k;cin>>n>>k;
    vector<ll>a(n+1);
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a.begin()+1,a.end());
    a.erase(unique(a.begin()+1,a.end()),a.end());
    n=(int)a.size()-1;
    for(int i=1;i<=n;i++) Q.emplace(a[i],i);
    int nums(0);
    ll pre=-1;
    while(!Q.empty()){
        auto [minl,idx]=Q.top();
        Q.pop();
        if(pre==minl) continue;
        pre=minl;
        if(++nums==k) return cout<<minl<<endl,0;
        for(int i=idx;i<=n;i++){
            Q.emplace(minl+a[i],i);
        }
    }
    cout<<0<<endl;
    return 0;
}
posted @ 2025-05-21 19:04  usedchang  阅读(9)  评论(0)    收藏  举报