2016 UESTC Training for Data Structures D - 卿学姐与魔法 CDOJ 1329 堆

D题:卿学姐与魔法

就是有两个长度为N的序列ABN<=1e5

然后输出A[i]+B[j]i可以等于j)组成的N*N个数中最小的N

 

可以用小根堆,也可以不用堆。

用堆的做法,把A数组升序排序,B可排可不排,然后可以得到N个序列

A[0]+B[0],A[1]+B[0],A[2]+B[0]....A[N-1]+B[0]

A[0]+B[1],A[1]+B[1],A[2]+B[1]....A[N-1]+B[1]

.....

A[0]+B[N-1],A[1]+B[N-1],A[2]+B[N-1]....A[N-1]+B[N-1]

然后我们把每个序列的第一个值都放入小根堆中,那么堆顶的元素一定就是最小的元素,假如这个数是A[i]+B[j],然后就把这个数弹出,把A[i+1]+B[j]加入到堆中,调整,然后堆顶元素也一定是最小的,再这样弹出+加入,弹出N个数,这N个数一定是最小的N个数。

我的代码就是这么写的,类似于一种N路归并排序的做法

 

还有一种做法就是不用堆的做法,

A数组和B数组都升序排序,

然后设置两个游标ij,初始ij都为0,因为A[0]+B[0]一定是最小的,然后后面有两种情况一种是++i,一种是++j,然后选取得到数小的那种,然后就这样啊,移动N次,得到N个数,这N个就是最小的N个数,这种做法我没去验证,但是应该是对的


代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <set>
using namespace std;
#define ll long long
#define maxn 100005
int N, a[maxn], b[maxn], ans[maxn];
struct Node
{
	int num, ai, bi;
	Node(){}
	Node(int n, int a, int b)
	{
		num = n, ai = a, bi = b;
	}
	void make(int n, int a, int b)
	{
		num = n, ai = a, bi = b;
	}
	bool operator <(Node x)const
	{
		return num < x.num;
	}
	bool operator >(Node x)const
	{
		return num > x.num;
	}
};
Node heap[maxn];
void heap_update()
{
	int k = 1;
	while (k <= N / 2)
	{
		if (heap[k] > heap[2 * k])
		{
			if (heap[k] > heap[2 * k + 1])
			{
				if (heap[2 * k] > heap[2 * k + 1])
				{
					Node t = heap[2 * k + 1];
					heap[2 * k + 1] = heap[k];
					heap[k] = t;
					k = 2 * k + 1;
				}
				else
				{
					Node t = heap[2 * k];
					heap[2 * k] = heap[k];
					heap[k] = t;
					k = 2 * k;
				}
			}
			else
			{
				Node t = heap[2 * k];
				heap[2 * k] = heap[k];
				heap[k] = t;
				k = 2 * k;
			}
		}
		else if (heap[k] > heap[2 * k + 1])
		{
			Node t = heap[2 * k + 1];
			heap[2 * k + 1] = heap[k];
			heap[k] = t;
			k = 2 * k + 1;
		}
		else
			break;
	}
}
int main()
{
	//freopen("input.txt", "r", stdin);
	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]);
	sort(a, a + N);
	sort(b, b + N);
	for (int i = 0; i < N; ++i)
	{
		heap[i + 1].make(a[i] + b[0], i, 0);
	}
	for (int i = N; i > 1; --i)
	{
		if (heap[i] < heap[i / 2])
		{
			Node t = heap[i / 2];
			heap[i / 2] = heap[i];
			heap[i] = t;
		}
	}
	for (int i = 0; i < N; ++i)
	{
		ans[i] = heap[1].num;
		heap[1].num = a[heap[1].ai] + b[heap[1].bi + 1];
		++heap[1].bi;
		heap_update();
	}
	for (int i = 0; i < N; ++i)
		printf("%d\n", ans[i]);
	//system("pause");
	//while (1);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值