洛谷 P3378 【模板】堆

洛谷 P3378 【模板】堆

洛谷 P3378 【模板】堆

菜鸟生成记(90)

复习一下数据结构的堆排序,顺带复习一下堆,在洛谷找个板子题练一下,还行;

这一题还可以用优先队列priorityqueue,STL yyds

[手写堆]

#include<iostream>
#include<stdio.h>
using namespace std;
const int N=1e6+10;
int a[N];
void heap1(int *a,int rt,int n) {//删除堆顶元素后,维护堆 
/*
维护小顶堆(堆顶为最小值) 
堆顶元素与堆底元素交换后,数组长度减1,堆顶元素出堆,
然后维护堆(重构堆),自顶向下维护堆 
*/ 
	int max1=rt;
	int l=2*rt;
	int r=2*rt+1;
	if(r<=n&&a[r]<a[max1]) {
		max1=r;
	}
	if(l<=n&&a[l]<a[max1]) {
		max1=l;
	}
	if(max1!=rt) {
		swap(a[max1],a[rt]);
		heap1(a,max1,n);//前往儿子(左或右) 
	}
}
void heap2(int *a,int rt) {//在堆底插入元素后,维护堆
/*
维护小顶堆(堆顶为最小值) 
堆底(数组尾部)插入一个元素,
自下而上维护堆 
*/
	if(a[rt]<a[rt/2]&&rt/2>=1){//判断是否小于父亲的值 
		swap(a[rt],a[rt/2]);//交换 
		heap2(a,rt/2);//前往父亲
	}
}
/*
8
1 3
1 5
1 6
1 2
1 7
2
3
2
*/
int main() {
	int t;
	int len=0;
	scanf("%d",&t);
	for(int i=0; i<t; i++) {
		int op;
		scanf("%d",&op);
		if(op==1) { //入堆(堆底插入元素)
			int x;
			scanf("%d",&x);
			a[++len]=x;
			heap2(a,len);//自下而上维护堆 
		} else if(op==2) { //输出最小元素
			printf("%d\n",a[1]);
		} else { //堆顶出堆(删除最小元素)
			swap(a[1],a[len]);//堆顶与堆底最后一个元素交换 
			len--;//堆底最后一个元素逻辑删除 
			heap1(a,1,len);//自上而下维护堆 
		}
	}
	return 0;
}

[优先队列priority_queue]

#include<iostream>
#include<stdio.h>
#include<vector>
#include<queue> 
using namespace std;
//创建小顶堆 ,以vector为辅助数组,参数:greater<int>(创建小顶堆);less<int>(创建大顶堆) 
priority_queue<int,vector<int>,greater<int> >q; 
int main() {
	int t;
	int len=0;
	scanf("%d",&t);
	for(int i=0; i<t; i++) {
		int op;
		scanf("%d",&op);
		if(op==1) { //入堆(堆底插入元素)
			int x;
			scanf("%d",&x);
			q.push(x);
		} else if(op==2) { //输出最小元素
			printf("%d\n",q.top());
		} else { //堆顶出堆(删除最小元素)
			q.pop();
		}
	}
	return 0;
}
### 关于 P4391 的解决方案 对于 P4391 题目,虽然未提供具体题目描述,但从常见的算法竞赛题目来看,该类问题通常涉及动态规划、贪心策略或其他高级数据结构的应用。以下是基于常见题型的一种可能解答方式。 #### 动态规划解决思路 假设问题是关于某种资源分配或路径优化的问题,则可以采用动态规划方法进行求解。以下是一个通用的 DP 实现框架: ```cpp #include <iostream> #include <vector> using namespace std; const int MAXN = 1e5 + 5; long long dp[MAXN]; // 定义状态转移数组 int n, m; // 假设输入参数分别为n和m void solve() { cin >> n >> m; // 输入处理 for (int i = 1; i <= n; ++i) { // 初始化dp数组 dp[i] = 0; } // 状态转移方程 for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { // 更新dp[i]的状态 dp[i] = max(dp[i], dp[i - 1] + some_function(i, j)); } } cout << dp[n] << endl; // 输出最终结果 } int main() { solve(); return 0; } ``` 以上代码仅为模板性质,实际应用需根据题目细节调整 `some_function` 和其他逻辑部分[^6]。 #### 贪心算法的可能性分析 如果题目适合使用贪心法解决,则可以通过局部最优选择逐步构建全局最优方案。例如,在某些区间覆盖或任务调度问题中,按照特定顺序排列事件能够显著简化计算过程。 ```cpp #include <bits/stdc++.h> using namespace std; struct Event { int start_time; int end_time; }; bool cmp(const Event& a, const Event& b) { return a.end_time < b.end_time; // 按结束时间升序排序 } int greedy_solution(vector<Event> events) { sort(events.begin(), events.end(), cmp); int count = 0, last_end = 0; for(auto event : events){ if(event.start_time >= last_end){ // 当前活动与已选无冲突 count++; last_end = event.end_time; } } return count; } int main(){ vector<Event> activities = {{...}, {...}}; // 替换为实际数据 cout<<greedy_solution(activities)<<endl; return 0; } ``` 此段程序展示了如何通过简单的比较操作快速找到最多可完成的任务数量[^7]。 #### 数据结构辅助技巧 针对更复杂的数据关系,合理运用 STL 中容器(如优先队列、双端队列等)往往能极大提升效率。比如利用维护最小/大值集合时非常高效。 ```cpp #include <queue> priority_queue<int,vector<int>,greater<int>> minHeap; minHeap.push(value); // 插入新元素value到小顶中 while(!minHeap.empty()){ process(minHeap.top());// 处理当前顶元素 minHeap.pop(); // 移除顶元素 } ``` 上述片段说明了标准库提供的优先级队列基本用法及其特性[^8]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值