二叉堆操作

P3378 【模板】堆

手写堆

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

int now,tail=0;
int heap[1000001];

void insert(int x)
{
	heap[++tail]=x;//从尾端入堆 
	int now=tail;
	while(now>1)//控制不越界,1的位置是根结点 
	{
		int fa=now/2;//父结点下标 
		if(heap[fa]<=heap[now]) return;//终止条件:父结点值小于等于当前位置的值,无需继续交换 
		swap(heap[fa],heap[now]);
		now=fa;//向上继续 
	}
}
void de()
{
	heap[1]=heap[tail--];//删除根结点,将堆结尾的数交换到根结点 
	now=1;
	while(now*2<=tail)//控制不越界 
	{
		int next=now*2;//next是左儿子,next+1是右儿子 
		if(next<tail&&heap[next+1]<heap[next]) next++;
		//右儿子存在,且其值小于左二子->当前位置与右儿子比较,否则与左儿子比较 
		if(heap[now]<=heap[next]) return;//终止条件:当前结点值小于等于儿子结点的值,无需继续交换 
		swap(heap[now],heap[next]);
		now=next;//向下继续 
	}
}
int main()
{
	int n,x,y;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&x);
		if(x==1)
		{
			scanf("%d",&y);
			insert(y);
		}
		if(x==2) printf("%d\n",heap[1]);
		if(x==3) de();
	}
}

STL-优先队列

#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int> >q;
int n,op,x;

int main()
{
	cin>>n;
	while(n--)
	{
		scanf("%d",&op);
		if(op==1) 
		{
			scanf("%d",&x);
			q.push(x);
		}
		if(op==2) printf("%d\n",q.top());
		if(op==3) q.pop();
	}
	return 0;
}

STL-堆 

#include<bits/stdc++.h>
using namespace std;
int heap[1000010];
int n,op,x,k;

int main()
{
	cin>>n;
	while(n--)
	{
		scanf("%d",&op);
		if(op==1) 
		{
			scanf("%d",&x);
			heap[++k]=x;
 			push_heap(heap+1,heap+1+k,greater<int>());  
		}
		if(op==2) printf("%d\n",heap[1]);
		if(op==3)
		{
			 pop_heap(heap+1,heap+1+k,greater<int>());  
 			 k--;    
		}
	}
	return 0;
}

天梯赛L2 关于堆的判断 (25 分)

将一系列给定数字顺序插入一个初始为空的小顶堆H[]。随后判断一系列相关命题是否为真。命题分下列几种:

  • x is the rootx是根结点;
  • x and y are siblingsxy是兄弟结点;
  • x is the parent of yxy的父结点;
  • x is a child of yxy的一个子结点。

输入格式:

每组测试第1行包含2个正整数N(≤ 1000)和M(≤ 20),分别是插入元素的个数、以及需要判断的命题数。下一行给出区间[−10000,10000]内的N个要被插入一个初始为空的小顶堆的整数。之后M行,每行给出一个命题。题目保证命题中的结点键值都是存在的。

输出格式:

对输入的每个命题,如果其为真,则在一行中输出T,否则输出F

输入样例:

5 4
46 23 26 24 10
24 is the root
26 and 23 are siblings
46 is the parent of 23
23 is a child of 10

输出样例:

F
T
F
T
#include<bits/stdc++.h> 
using namespace std;
int n,m,sheap[1010],k=0;

int find(int x)
{
	for(int i=1;i<=k;i++)
		if(sheap[i]==x) return i;
	return 0;
}

void build_small_heap(int x)
{
	sheap[++k]=x;
	int now=k;
	while(now>1)
	{
		int fa=now/2;
		if(sheap[fa]>sheap[now])
		{
			swap(sheap[fa],sheap[now]);
			now=fa;
		}
		else break;
	}
}

int main()
{
	cin>>n>>m;
	for(int i=0;i<n;i++)
	{
		int x;
		scanf("%d",&x);
		build_small_heap(x);
	}
	while(m--)
	{
		int x;
		cin>>x;
		string s;
		cin>>s;
		if(s=="and")
		{
			int y;
			string s1,s2;
			cin>>y>>s1>>s2;
			if(find(x)/2==find(y)/2)
				cout<<"T"<<endl;
			else cout<<"F"<<endl;
		}
		else if(s=="is")
		{
			string ss;
			cin>>ss;
			if(ss=="the")
			{
				string sss;
				cin>>sss;
				if(sss=="root")
				{
					if(find(x)==1)
						cout<<"T"<<endl;
					else cout<<"F"<<endl;
				}
				else if(sss=="parent")
				{
					string s1;
					int y;
					cin>>s1>>y;
					if(find(y)/2==find(x))
						cout<<"T"<<endl;
					else cout<<"F"<<endl;
				}
			}
			else if(ss=="a")
			{
				string s1,s2;
				int y;
				cin>>s1>>s2>>y;
				if(find(x)/2==find(y))
					cout<<"T"<<endl;
				else cout<<"F"<<endl;
			}
		}
	}
	return 0;
}

UVA1316 Supermarket

  • 给定 n 件物品,第 i 件物品有如下信息:
    • 卖出去可以得到 p_i 的收益。
    • 过期时间为 d_i,过了过期时间就不能再卖出去。
  • 卖掉一件物品要用 1天的时间,求最大收益。
  • 多组数据,每组数据一行,首先一个整数 n 然后 n 对数 p_i,d_i,以文件终止符结束。
  • 0<=n<=1e4,1<=p_i,d_i<=1e4

 

#include<bits/stdc++.h>
using namespace std;
const int N = 10005;

struct Node 
{
	int val, day;
} product[N];

bool cmp(Node x,Node y)
{
	if(x.day!=y.day) return x.day<y.day;
	else return x.val>y.val;
}

int main()
{
	int n;
	while (cin>>n) 
	{
		memset(product,0,sizeof(product));
		priority_queue<int,vector<int>,greater<int> >q;//小根堆 
		int ans=0;
		for(int i=1;i<=n;i++)
			scanf("%d %d",&product[i].val,&product[i].day);
		sort(product + 1, product + n + 1, cmp); 
		//排序,把先过期的排在前面 
		for(int i=1;i<=n;i++)
		{
			if(q.size()==product[i].day&&product[i].val>q.top())
			//前面的“售卖日程”已经排满了,看看是否可以替换 (从堆顶取出最小的与当前值进行比较) 
			{
				q.pop();
				q.push(product[i].val);//替换完成 
			}
			else if(q.size()<product[i].day)
			//前面的售卖日程没有排满,可以直接安排在前面的一天 
				q.push(product[i].val);
		}
		while(q.size())//统计堆中的所有商品总利润 
		{
			int temp=q.top();
			q.pop();
			ans+=temp;
		}
		cout<<ans<<endl;
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

春弦_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值