Skip to content

12108: 【原2108】配对 I

题目

题目描述

author: 蒋舜宁 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/2108

Description

DS接到一个任务,这个任务有很多部分,每一个部分需要两个人完成,自然就要进行配对。

本次配对的具体要求教务处已经下发:

1) 一共\( 2 \times N \)个人,分为两个队伍,每队\( N \)人,每个人都有一个工作能力评估值(可以相同)。总共需要配出\( N \)对,每对两个人。

2) 每个人可以被配对多次,每一对中的两个人分别来自不同队伍。

3) 要求中提到,需要得到工作能力评估值之和最小的\( N \)对。

请你帮忙进行配对。

Input Format

输入共有三行。

第一行一个整数\( N \),意义如上。

第二行有\( N \)个整数,分别表示第一个队伍中每个人的工作能力评估值。

第三行有\( N \)个整数,分别表示第二个队伍中每个人的工作能力评估值。

Output Format

共\( N \)行,每行一个整数,表示每一对的工作能力评估值之和。

按照升序输出。

Sample Input

4
2 7 4 5
8 3 1 4

Sample Output

3
5
5
6

About Test Data

对于30%数据 \(1 \leq N \leq 800\)。

对于100%数据 \(1 \leq N \leq 200,000\)。

所有工作能力评估值\(\leq 100,000,000\)。

样例解释:

2+1, 2+3, 4+1, 2+4

WashSwang's solution

#include <iostream>
#include <cstring>
using namespace std;
int n,heap[500000],p[500000],len,a[300000],b[300000],q[500000];
void minheapify(int x){
    int smallest=x,l,r;
    while (true) {
        l=x<<1;
        r=l+1;
        if (l <= len && heap[l] < heap[x]) smallest = l;
        if (r <= len && heap[r] < heap[smallest]) smallest = r;
        if (smallest != x) {
            swap(heap[smallest],heap[x]);
            swap(p[smallest],p[x]);
            x = smallest;
        }
        else break;
    }
}
int pop(){
    int ret=heap[1];
    q[p[1]]++;
    heap[1]=a[p[1]]+b[q[p[1]]];
    minheapify(1);
    return ret;
}
void qsort(int l,int r){
    if (l+1>=r) return;
    int i=l,j=r-1,key=b[l];
    while (i<j){
        while (i<j&&b[j]>=key) j--;
        if (i<j) b[i++]=b[j];
        while (i<j&&b[i]<=key) i++;
        if (i<j) b[j--]=b[i];
    }
    b[i]=key;
    qsort(l,i);
    qsort(i+1,r);
}
int main() {
    scanf("%d",&n);
    for (int i=0;i<n;++i) scanf("%d",&a[i]);
    for (int i=0;i<n;++i) scanf("%d",&b[i]);
    qsort(0,n);
    len=n;
    for (int i=1;i<=n;++i)
    {
        heap[i]=a[i-1]+b[0];
        p[i]=i-1;
        q[i]=0;
    }
    for (int i=n>>1;i>=1;--i) minheapify(i);
    for (int i=0;i<n;++i)
        printf("%d\n",pop());
    return 0;
}

yyong119's solution

#include <cstdio>
#include <queue>
#include <algorithm>
// #include <map>
#define MAX_N 200010
#define KEY 10000007
using namespace std;
struct Node {
    int x, y, v;
    Node(int i = 0, int j = 0, int p = 0): x(i), y(j), v(p) {}
    bool operator<(const Node &p) const {
        return v > p.v;
    }
};
int n;
int a[MAX_N], b[MAX_N];
bool my_hash[KEY];
// map<long long, bool> um;
priority_queue<Node> q;
inline int read() {
    char ch = getchar(); int res = 0, flag = 1;
    while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if (ch == '-') flag = -1, ch = getchar();
    while (ch >= '0' && ch <= '9')
        res = (res << 3) + (res << 1) + (ch ^ 48), ch = getchar();
    return res * flag;
}
int main() {
    n = read();
    for (register int i = 0; i < n; ++i) a[i] = read();
    for (register int i = 0; i < n; ++i) b[i] = read();
    sort(a, a + n); sort(b, b + n);
    q.push(Node(0, 0, a[0] + b[0]));
    for (register int i = 0; i < n; ++i) {
        // print the current minimun
        Node cur = q.top(); printf("%d\n", cur.v); q.pop();
        // solve for next possible numbers
        int x_c = cur.x, x_n = x_c + 1, y_c = cur.y, y_n = y_c + 1;
        long long x_p = ((long long) x_n << 18) | y_c, y_p = ((long long) x_c << 18) | y_n;
        int x_p_m = x_p % KEY, y_p_m = y_p % KEY;
        // (x_n, y_c) is valid and has not been in queue
        // if (x_n < n && um.find(x_p) == um.end()) {
        if (x_n < n && !my_hash[x_p_m]) {
            q.push(Node(x_n, y_c, a[x_n] + b[y_c]));
            // um[x_p] = true;
            my_hash[x_p_m] = true;
        }
        // (x_c, y_n) is valid and has not been in queue
        // if (y_n < n && um.find(y_p) == um.end()) {
        if (y_n < n && !my_hash[y_p_m]) {
            q.push(Node(x_c, y_n, a[x_c] + b[y_n]));
            // um[y_p] = true;
            my_hash[y_p_m] = true;
        }
    }
    return 0;
}