站外题求助

给定一个包含N个整数的数组。请从数组中选出M组有序数对

每组有序数对由数组中的 两个元素组成,且每组有序数对 只能用一次。请编程计算出,在给定的数组中,选出的 M组 有序数对的和的最大值是多少。

本题中的有序数对,指的是符合如下两个条件 其中之一数对: 从N个数中,选出两个不同位置的整数。比如第 i个数Ai和第 j个数Aj( i≠j),则Ai,Aj和Aj,Ai 为两组不同的有序数对。

  1. 从N个数中,选出同一个位置的整数2 次,组成一组有序数对。比如第i个数Ai,Ai 即构成一组有序数对。 输入 第一行包含两个整数 N和M ,分别表示数组中元素的个数和需要选择的有序数对数量。
  2. 第二行包含 N个整数 A1,A2,...,AN ,表示数组中的每个元素的值。 输出 输出一个整数,表示选出的 M个有序数对的和的最大值。 样例 输入

    5 3
    34 33 10 14 19
    

    输出

    202
    

    输入

    9 14
    110 24 21 34 1 3 5 5 3
    

    输出

    1837
    

    输入

    9 73
    64141 40773 79105 16076 67597 52981 5828 66249 75177
    

    输出

    8128170
    

    34,33,10,14,19,需要选3个有序数对。

    一种可能的方案:

    • (34,34) ,和为34+34=68 ;
    • (34,33) ,和为 34+33=67 ;
    • (33,34) ,和为33+34=67; 总和为68+67+67=202。
    • 数据范围

      对于 15% 的数据,满足所有的 Ai 全部相同。

      对于50%的数据,满足1≤N≤100 。

      对于100%的数据,满足 1≤N≤10^5,1≤M≤N^2 , 1≤Ai≤10^5 。

#include <bits/stdc++.h>
using namespace std;
 
struct Node{
    long long sum;
    int i;
    int j;
    Node(long long s, int i_, int j_) : sum(s), i(i_), j(j_) {}
    bool operator<(const Node& other) const {
        return sum < other.sum;
    }
};
 
int main() {
    int n, m;
    cin >> n >> m;
    vector<long long> A(n);
    for (int i = 0; i < n; ++i) {
        cin >> A[i];
    }
    sort(A.rbegin(), A.rend());
    priority_queue<Node> pq;
    unordered_set<long long> vis;
    if (n >= 1) {
        long long tmp = 0LL * (n + 1) + 0;
        vis.insert(tmp);
        pq.emplace(A[0] + A[0], 0, 0);
    }
    if (n >= 2) {
        long long tmp = 0LL * (n + 1) + 1;
        vis.insert(tmp);
        pq.emplace(A[0] + A[1], 0, 1);
    }
    long long ans = 0;
    int remaining = m;
    while (remaining > 0 && !pq.empty()) {
        Node node = pq.top();
        pq.pop();
        long long s = node.sum;
        int i = node.i;
        int j = node.j;
        int count = (i == j) ? 1 : 2;
        int take = min(count, remaining);
        ans += take * s;
        remaining -= take;
        if (remaining == 0) {
            break;
        }
        if (i == j) {
            int ni = i + 1;
            int nj = j + 1;
            if (ni < n && nj < n) {
                long long tmp = 1LL * ni * (n + 1) + nj;
                if (!vis.count(tmp)) {
                    vis.insert(tmp);
                    pq.emplace(A[ni] + A[nj], ni, nj);
                }
            }
        } else {
            int nj = j + 1;
            if (nj < n) {
                long long tmp = 1LL * i * (n + 1) + nj;
                if (!vis.count(tmp)) {
                    vis.insert(tmp);
                    pq.emplace(A[i] + A[nj], i, nj);
                }
            }
            int ni = i + 1;
            if (ni < j) {
                long long tmp = 1LL * ni * (n + 1) + j;
                if (!vis.count(tmp)) {
                    vis.insert(tmp);
                    pq.emplace(A[ni] + A[j], ni, j);
                }
            }
        }
    }
    cout << ans;
    return 0;
}

有没有大佬给个思路或调一下代码

全部评论
6这么简单都不会
点赞 回复 分享
发布于 2025-10-08 10:15 广东

相关推荐

2025-12-25 16:26
已编辑
河北科技学院 Java
勇敢的牛油不服输:2800-300那不等于2500一个月吗兄弟们
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务