W10(Heap)

7-1 Windows消息队列

分数 25

 

全屏浏览题目

 

切换布局

作者 DS课程组

单位 浙江大学

消息队列是Windows系统的基础。对于每个进程,系统维护一个消息队列。如果在进程中有特定事件发生,如点击鼠标、文字改变等,系统将把这个消息加到队列当中。同时,如果队列不是空的,这一进程循环地从队列中按照优先级获取消息。请注意优先级值低意味着优先级高。请编辑程序模拟消息队列,将消息加到队列中以及从队列中获取消息。

输入格式:

输入首先给出正整数N(≤105),随后N行,每行给出一个指令——GETPUT,分别表示从队列中取出消息或将消息添加到队列中。如果指令是PUT,后面就有一个消息名称、以及一个正整数表示消息的优先级,此数越小表示优先级越高。消息名称是长度不超过10个字符且不含空格的字符串;题目保证队列中消息的优先级无重复,且输入至少有一个GET

输出格式:

对于每个GET指令,在一行中输出消息队列中优先级最高的消息的名称和参数。如果消息队列中没有消息,输出EMPTY QUEUE!。对于PUT指令则没有输出。

输入样例:

9
PUT msg1 5
PUT msg2 4
GET
PUT msg3 2
PUT msg4 4
GET
GET
GET
GET

输出样例:

msg2
msg3
msg4
msg1
EMPTY QUEUE!

 

#include <iostream>
#include <queue>
#include <string>
using namespace std;

struct node
{
	char message[11];
	int rank;
	friend bool operator<(node a, node b)
	{
		return a.rank > b.rank;
	}
};
priority_queue<node> q;

int main()
{
	string op;
	node p;
	int n;
	scanf("%d", &n);
	for (int i = 0; i < n; i++)
	{
		cin >> op;
		if (op[0] == 'P')
		{
			cin >> p.message >> p.rank;
			//printf("%s  %s", p.message, p.rank);
			q.push(p);
		}
		else if (op[0] == 'G')
		{
			if (q.empty())
				printf("EMPTY QUEUE!\n");
			else
			{
				printf("%s\n", q.top().message);
				q.pop();
			}
		}
	}
	return 0;

}

 

7-2 笛卡尔树

分数 25

 

全屏浏览题目

 

切换布局

作者 DS课程组

单位 浙江大学

笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字满足优先队列(不妨设为最小堆)的顺序要求,即该结点的K2值比其子树中所有结点的K2值小。给定一棵二叉树,请判断该树是否笛卡尔树。

输入格式:

输入首先给出正整数N(≤1000),为树中结点的个数。随后N行,每行给出一个结点的信息,包括:结点的K1值、K2值、左孩子结点编号、右孩子结点编号。设结点从0~(N-1)顺序编号。若某结点不存在孩子结点,则该位置给出−1。

输出格式:

输出YES如果该树是一棵笛卡尔树;否则输出NO

输入样例1:

6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 21 -1 4
15 22 -1 -1
5 35 -1 -1

输出样例1:

YES

输入样例2:

6
8 27 5 1
9 40 -1 -1
10 20 0 3
12 11 -1 4
15 22 -1 -1
50 35 -1 -1

输出样例2:

NO
#include <bits/stdc++.h>
using namespace std;

int n;
struct tree
{
	int k1, k2;
	int left, right;
} node[1010];

int vis[1010] = {0};
vector<int> t;

void BST(int root)
{
	if (node[root].left != -1)
		BST(node[root].left);
	t.push_back(node[root].k1);
	if (node[root].right != -1)
		BST(node[root].right);
}

bool isBST(int root)
{
	BST(root);
	for (int i = 0; i < n - 1; i++)
		if (t[i] > t[i + 1])
			return false;
	return true;
}

bool isMinHeap(int root)
{
	if (root == -1)
		return true;
	if (node[root].left != -1)
	{
		if (node[node[root].left].k2 < node[root].k2)
			return false;
		else if (!isMinHeap(node[root].left))
			return false;
	}
	if (node[root].right != -1)
	{
		if (node[node[root].right].k2 < node[root].k2)
			return false;
		else if (!isMinHeap(node[root].right))
			return false;
	}
	return true;
}

int main()
{
	int root = 0;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> node[i].k1 >> node[i].k2 >> node[i].left >> node[i].right;
		if (node[i].left != -1)
			vis[node[i].left] = 1;//非根节点置1
		if (node[i].right != -1)
			vis[node[i].right] = 1;
	}
	for (int i = 0; i < n; i++)
		if (vis[i] == 0)
			root = i;//找到根节点编号
	if (isBST(root) && isMinHeap(root))
		cout << "YES" << endl;
	else
		cout << "NO" << endl;

}

7-3 特殊堆栈

分数 25

 

全屏浏览题目

 

切换布局

作者 陈越

单位 浙江大学

堆栈是一种经典的后进先出的线性结构,相关的操作主要有“入栈”(在堆栈顶插入一个元素)和“出栈”(将栈顶元素返回并从堆栈中删除)。本题要求你实现另一个附加的操作:“取中值”——即返回所有堆栈中元素键值的中值。给定 N 个元素,如果 N 是偶数,则中值定义为第 N/2 小元;若是奇数,则为第 (N+1)/2 小元。

输入格式:

输入的第一行是正整数 N(≤105)。随后 N 行,每行给出一句指令,为以下 3 种之一:

Push key
Pop
PeekMedian

其中 key 是不超过 105 的正整数;Push 表示“入栈”;Pop 表示“出栈”;PeekMedian 表示“取中值”。

输出格式:

对每个 Push 操作,将 key 插入堆栈,无需输出;对每个 Pop 或 PeekMedian 操作,在一行中输出相应的返回值。若操作非法,则对应输出 Invalid

输入样例:

17
Pop
PeekMedian
Push 3
PeekMedian
Push 2
PeekMedian
Push 1
PeekMedian
Pop
Pop
Push 5
Push 4
PeekMedian
Pop
Pop
Pop
Pop

输出样例:

Invalid
Invalid
3
2
2
1
2
4
4
5
3
Invalid
#include <bits/stdc++.h>
using namespace std;

vector<int> v1, v2;

int main()
{
	vector<int>::iterator it;
	int n, x, cnt;
	string op;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		cin >> op;
		if (op == "Push")
		{
			cin >> x;
			v1.push_back(x);
			it=lower_bound(v2.begin(),v2.end(),x);
			v2.insert(it,x);
		}
		else if (op == "Pop")
		{
			if (v1.empty())
				cout << "Invalid" << endl;
			else
			{
				cout << v1.back() << endl;
				it = lower_bound(v2.begin(), v2.end(), v1.back());
				v2.erase(it);
				v1.pop_back();
			}
		}
		else if (op == "PeekMedian")
		{
			if (v1.empty())
				cout << "Invalid" << endl;
			else
			{
				cnt = (int)v2.size();
				if (cnt % 2 == 1)
					x = (cnt + 1) / 2 - 1;
				else
					x = cnt / 2 - 1;
				cout << v2[x] << endl;

			}
		}

	}
}

 

7-4 修理牧场

分数 25

 

全屏浏览题目

 

切换布局

作者 DS课程组

单位 浙江大学

农夫要修理牧场的一段栅栏,他测量了栅栏,发现需要N块木头,每块木头长度为整数Li​个长度单位,于是他购买了一条很长的、能锯成N块的木头,即该木头的长度是Li​的总和。

但是农夫自己没有锯子,请人锯木的酬金跟这段木头的长度成正比。为简单起见,不妨就设酬金等于所锯木头的长度。例如,要将长度为20的木头锯成长度为8、7和5的三段,第一次锯木头花费20,将木头锯成12和8;第二次锯木头花费12,将长度为12的木头锯成7和5,总花费为32。如果第一次将木头锯成15和5,则第二次锯木头花费15,总花费为35(大于32)。

请编写程序帮助农夫计算将木头锯成N块的最少花费。

输入格式:

输入首先给出正整数N(≤104),表示要将木头锯成N块。第二行给出N个正整数(≤50),表示每段木块的长度。

输出格式:

输出一个整数,即将木头锯成N块的最少花费。

输入样例:

8
4 5 1 2 1 3 1 1

输出样例:

49
#include <bits/stdc++.h>
using namespace std;
#define maxn 10005
 
priority_queue<int, vector<int>, greater<int>> p;
//优先队列默认是大顶堆(less)
//sort默认是小顶堆(less)
int main()
{
	int n;
	cin >> n;
	for (int i = 0; i < n; i++)
	{
		int num;
		cin >> num;
		p.push(num);
	}
	long long ans = 0;
	while (!p.empty())
	{
		int a = p.top();
		p.pop();
		if (p.empty())
			break;
		int b = p.top();
		p.pop();
		int c = a + b;
		ans += c;
		p.push(c);
	}
 
	cout << ans;
	return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

102101222_张凯权

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值