zoukankan      html  css  js  c++  java
  • ACWing 146 Sequence

    题意简述

    给定(M)个长度为(N)的序列,从每个序列中任取一个数求和,求前(N)小和。
    数据范围见题

    简单口胡

    • (M = 1)
      把原序列排个序输出完事。
    • (M = 2)
      我们将两个序列分别假设为(a,b),并已经将其排好序。

    定义:

    1. (k)小和为(F(k))
    2. (a_i + b_j)可能是(F(k))的答案,我们称二元组((i,j))(F(k))候选二元组
    3. (a_i + b_j)(F(k))的答案,我们称二元组((i,j))(F(k))答案二元组

    Solution:
    首先(F(1))答案二元组显然为((1,1))
    考虑(F(2))候选二元组,有((1,2),(2,1)),这些都有可能。
    假设(F(2))答案二元组((2,1)),那么(F(3))候选二元组即为((1,2),(2,2),(3,1))
    我们会发现,如果((x,y))(F(k))答案二元组,那么((x + 1,y))((x,y + 1))就是(F(k + 1))候选二元组
    原因:(a_{x + 1})是在(a)中比(a_{x})大的最小的数,也就是说排名有可能只会(+1)(b_{y + 1})(b_y)同理,所以它们是候选二元组

    • (M > 2)

    用优先队列维护一下,每次先处理前面两排,然后将答案合并再与下一排进行计算。

    但是我们会发现有时同时更新出((x + 1,y))((x,y + 1))会更新出相同的二元组。
    原因:设(F(k))答案二元组((x_0,y_0))
    那么(F(k + 1))候选二元组就包含((x_0 + 1,y_0),(x_0,y_0 + 1))
    (F(k_0)(k_0 > k))答案二元组((x_0 + 1,y_0)),那么其会整出((x_0 + 2,y_0),(x_0 + 1,y_0 + 1))
    (F(k_1)(k_1 > k))答案二元组((x_0,y_0 + 1)),那么其会整出((x_0,y_0 + 2),(x_0 + 1,y_0 + 1)),与上面的((x_0 + 1,y_0 + 1))冲突。

    这里你可以用map / hash 判断,也可以用《算法竞赛进阶指南》上的方法,这里不叙述,也可以看代码。

    # include <bits/stdc++.h>
    using namespace std;
    int t;
    int m,n;
    
    const int M = 1005,N = 2005;
    
    int a[M][N];
    
    int nowi,nowj;
    
    int A[N]; // cun chu
    
    struct node
    {
        int x,y;
        bool flag; // flag = 0 -> y + 1    flag = 1 -> x + 1;
        node() {}
        node(int _x,int _y,bool f) : x(_x),y(_y),flag(f) {}
    };
    
    bool operator < (const struct node &x,const struct node &y)
    {
        return a[nowi][x.x] + a[nowj][x.y] > a[nowi][y.x] + a[nowj][y.y];
    }
    
    priority_queue <node> q;
    
    void solve(void)
    {
        while(!q.empty()) q.pop();
        q.push(node(1,1,0));
        int tot = 0;
        while(tot < n)
        {
            node X = q.top();q.pop();
            q.push(node(X.x,X.y + 1,1));
            if(X.flag == 0) q.push(node(X.x + 1,X.y,0));
            A[++tot] = a[nowi][X.x] + a[nowj][X.y];
        }
        for(int i = 1; i <= n; i++) a[nowj][i] = A[i];
        return;
    }
    
    int main(void)
    {  
        scanf("%d",&t);
        while(t--)
        {   
            scanf("%d%d",&m,&n);
            for(int i = 1; i <= m; i++)
            {
                for(int j = 1; j <= n; j++)
                {
                    scanf("%d",&a[i][j]);
                }
                sort(a[i] + 1,a[i] + n + 1);
            }
            if(m == 1)
            {
                for(int i = 1; i <= n; i++)
                {
                    printf("%d ",a[1][i]);
                }
                putchar('
    ');
                continue;
            }
            nowi = 1,nowj = 2;
            while(nowj <= m)
            {   
                solve();
                ++nowi,++nowj;
            }
            for(int i = 1; i <= n; i++)
            {
                printf("%d ",a[m][i]);
            }
            putchar('
    ');
        }
        
        return 0;
    }
    //Sequence luyiming123
    
  • 相关阅读:
    如何快速搞定websocket
    websocket断网消息补发
    div嵌套多个点击事件,点击后如何阻止多次事件触发冒泡
    仿照 MediatR实现了一个中介者模式Publish功能,使用同MediatR
    git提交指南(超级详细)
    删除github中的文件夹
    抽取进程集成模式注册报错,OGG-08221,OCI Error ORA-44004 invalid qualified SQL Name
    Oracle-参数学习_no_or_expansion
    OGG19版本源端新增字段,目标端复制进程不报错,使用MAPALLCOLUMNS进行测试
    Oracle存储过程如何定位慢SQL?
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/14354606.html
Copyright © 2011-2022 走看看