AcWing 146.序列

网址如下:146. 序列 - AcWing题库

有点坑,这题

刚开始我写的代码选择的序列是有遗漏的,直接WA,然后我继续对全局进行处理,但是一次求最小插入的节点太多了,直接MLE,最后是看算法书里的解,发现是先对两个序列求前n小的序列,得到的新序列有可以和下一个序列求前n小,以此类推,最后就求到题目要求的序列

MLE代码:

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 2010;
const int maxm = 1010;
int m, n;
int A[maxm][maxn];
struct Node{
    int p[maxm];
    int last;
    Node():p{}, last(m){}
    bool operator<(const Node &tt)const{
        int sum = 0, tt_sum = 0;
        for(int i = 0; i < m; i++){sum += A[i][p[i]]; tt_sum += A[i][tt.p[i]];}
        return sum > tt_sum;
    }
};

int main(void)
{
    int T; scanf("%d", &T);
    while(T--){
        scanf("%d%d", &m, &n);
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++)
                scanf("%d", &A[i][j]);
            sort(A[i], A[i] + n);
        }
        //开始计算
        priority_queue<Node, vector<Node> > pq; pq.push(Node());
        for(int i = 0; i < n; i++){
            Node u = pq.top(); pq.pop();
            int last = u.last, ans = 0;
            for(int i = 0; i < m; i++) ans += A[i][u.p[i]]; printf("%d ", ans);
            for(int i = 0; i < last; i++){
                u.p[i]++; u.last = i + 1;
                if(u.p[i] < n) pq.push(u);
                u.p[i]--;
            }
        }
        
        putchar('\n');
    }

    return 0;
}

AC代码:

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;

const int maxn = 2010;
const int maxm = 1010;
int m, n;
int A[maxn], B[maxn], res[maxn];
struct Node{
    int i, j;
    bool last;
    Node():i(0), j(0), last(false){}
    Node(int i, int j, bool last):i(i), j(j), last(last){}
    bool operator<(const Node &tt)const{return A[i] + B[j] > A[tt.i] + B[tt.j];}
};
inline void join(void){
    priority_queue<Node, vector<Node> > pq; pq.push(Node());
    for(int i = 0; i < n; i++){
        Node u = pq.top(); pq.pop();
        if(!u.last && u.i + 1 < n) pq.push(Node(u.i + 1, u.j, false));
        if(u.j + 1 < n) pq.push(Node(u.i, u.j + 1, true));
        res[i] = A[u.i] + B[u.j];
    }
    memcpy(A, res, sizeof(A));
}

int main(void)
{
    int T; scanf("%d", &T);
    while(T--){
        scanf("%d%d", &m, &n);
        for(int i = 0; i < n; i++) scanf("%d", &A[i]);
        sort(A, A + n);
        for(int i = 1; i < m; i++){
            for(int j = 0; j < n; j++) scanf("%d", &B[j]);
            sort(B, B + n);
            join();
        }
        for(int i = 0; i < n; i++) printf("%d ", A[i]);
        putchar('\n');
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值