P1631 序列合并

首先,把A和B两个序列分别从小到大排序,变成两个有序队列。这样,从A和B中各任取一个数相加得到N2个和,可以把这些和看成形成了n个有序表/队列:

A[1]+B[1] <= A[1]+B[2] <= … <= A[1]+B[N]

A[2]+B[1] <= A[2]+B[2] <= … <= A[2]+B[N]

……

A[N]+B[1] <= A[N]+B[2] <= … <= A[N]+B[N]

接下来,就相当于要将这N个有序队列进行合并排序:

首先,将这N个队列中的第一个元素放入一个堆中;

然后;每次取出堆中的最小值。若这个最小值来自于第k个队列,那么,就将第k个队列的下一个元素放入堆中。

假设我们当前取出的是a[i]+b[j],那么我们下一次取的就是a[i]+b[j+1]或a[i+1]+b[j]。我们先把b序列中所有数与a[1]的和放入优先队列,这样就满足了a[i]+b[j+1]的情况。所以重点就是处理a[i+1]+b[j],每次把取出b[j]对应的取到a数组中的位置往后移一个加入优先队列即可。

const int N=1e5+10;
struct Node
{
    int i,j;
    int sum;
    bool operator>(const Node &W) const
    {
        return sum > W.sum;
    }
};
int a[N],b[N];
int n;

int main()
{
    cin>>n;

    for(int i=0;i<n;i++) cin>>a[i];

    priority_queue<Node,vector<Node>,greater<Node>> heap;
    for(int i=0;i<n;i++)
    {
        cin>>b[i];
        heap.push({i,0,a[i]+b[0]});
    }

    for(int i=0;i<n;i++)
    {
        Node t=heap.top();
        heap.pop();

        cout<<t.sum<<' ';
        heap.push({t.i,t.j+1,a[t.i]+b[t.j+1]});
    }
    cout<<endl;
    //system("pause");
    return 0;
}
posted @ 2021-02-26 21:39  Dazzling!  阅读(69)  评论(0编辑  收藏  举报