zoukankan      html  css  js  c++  java
  • 0x10基本数据结构(0x17 二叉堆)例题2:序列

    题意

    题目链接

    【题意】
    给定m个序列,每个包含n个非负整数。
    现在我们可以从每个序列中选择一个数字以形成具有m个整数的序列。
    很明显,我们一共可以得到n^m个这种序列, 然后我们可以计算每个序列中的数字之和,并得到n^m个值。
    现在请你求出这些序列和之中最小的n个值。 
    
     【输入格式】
    第一行输入一个整数T,代表输入中包含测试用例的数量。
    接下来输入T组测试用例。
    对于每组测试用例,第一行输入两个整数m和n。
    接下在m行输入m个整数序列,数列中的整数均不超过10000。 
    
     【输出格式】
    对于每组测试用例,均以递增顺序输出最小的n个序列和,数值之间用空格隔开。
    每组输出占一行。 
    
     【数据范围】
    0<m≤1000
    0<n≤2000 
    
      【输入样例】
    1
    2 3
    1 2 3
    2 2 3 
    
      【输出样例】
    3 3 4 
    

    题解

    这道题目,我们一开始看是蒙的。

    但是看了YXC巨佬的视频不就会了吗。

    这道题目,我们不能直接算(m)个序列的(m)小值。

    我们发现其实我们可以算出第(1)和第(2)个序列第前(n)小的序列和,然后把这(n)项当成一个新的序列。

    很容易想,(1,2,3)的前(n)小序列和其实就是(1,2)的前(n)小的序列然后和(3)序列合并。(这个很好证)。

    所以我们只要合并(m-1)次序列成一个序列,然后这个序列就是答案。

    那么对于两个序列我们如何算出其前(n)小。

    我们把第一个序列(a)排序,然后看第二个序列(b),很明显,第(1)小的肯定在(a_{1}+b_{1},a_{1}+b_{2},...)中产生,那么我们就建个堆,把这个丢进去。

    然后对于最小的(a_{1}+b_{i}),那么第二小就会在上面那坨除(a_{1}+b_{i})(a_{2}+b_{i})中产生,再把(a_{2}+b_{i})丢进堆就行了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define  N  2100
    using  namespace  std;
    struct  node
    {
    	int  x,id/*表示是哪一行*/;
    	node(int  xx,int  yy){x=xx;id=yy;}
    };
    inline  bool  operator<(node  x,node  y){return  x.x>y.x;}
    priority_queue<node>ss;
    int  a[N][N],n,m;
    int  b[N],c[N],now[N];
    void  merge(int  x1,int  x2)
    {
    	memcpy(b,a[x1],sizeof(b));memcpy(c,a[x2],sizeof(c));
    	while(!ss.empty())ss.pop();
    	sort(b+1,b+n+1);
    	for(int  i=1;i<=n;i++)ss.push(node(b[1]+c[i],i)),now[i]=1;
    	for(int  i=1;i<n;i++)
    	{
    		a[x2][i]=ss.top().x;int  x=ss.top().id;
    		ss.pop();
    		if(now[x]<n)ss.push(node(c[x]+b[++now[x]],x));
    	}
    	a[x2][n]=ss.top().x;
    }
    int  main()
    {
    	int  T;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]);
    		}
    		if(m==1)
    		{
    			sort(a[1]+1,a[1]+n+1);
    			for(int  i=1;i<n;i++)printf("%d ",a[m][i]);
    			printf("%d
    ",a[m][n]);
    			continue;
    		}
    		for(int  i=2;i<=m;i++)merge(i-1,i);
    		for(int  i=1;i<n;i++)printf("%d ",a[m][i]);
    		printf("%d
    ",a[m][n]);
    	}
    	return  0;
    }
    
  • 相关阅读:
    微信小程序音频播放
    jsonp跨域请求-最简单的方法
    mysql explain 正常,但是实际上是全盘扫描
    lnmp运行过程中出现502处理方法
    [Python]利用type()动态创建类
    Django-form表单
    Django-认证系统
    Django-model基础
    Django-MTV
    前端基础之:JQuery(可编辑版)
  • 原文地址:https://www.cnblogs.com/zhangjianjunab/p/11737542.html
Copyright © 2011-2022 走看看