蓝桥杯整数删除(优先队列&&pair,模拟链表)

题目:给定一个长度为 N 的整数数列:A1, A2, ... , AN。你要重复以下操作 K 次:

每次选择数列中最小的整数(如果最小值不止一个,选择最靠前的),将其删除。

并把与它相邻的整数加上被删除的数值。

输出 K 次操作后的序列。

第一行包含两个整数 N 和 K。

第二行包含 N 个整数,A1, A2, ... , AN。

对于 20% 的数据,1 ≤ K < N ≤ 10000。

对于 100% 的数据,1 ≤ K < N ≤ 5 × 1e5,0 ≤ Ai ≤ 1e8。

输入

复制代码
5 3
1 4 2 8 7

输出

复制代码
17 7

暴力:for循环找最小值,o(n**2)超了,用vector删除优点是不需要模拟链表的删除过程,不需要实时记录被删除的数的索引,(注意min值是要在每个K循环之前都要更新的,呜呜,一开始我在循环外更新,就出错了,找了好久才发现错因)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3f
#define int long long
int n,k;
vector<int> v(5e5);
signed main()
{
	cin>>n;
	cin>>k;
	for(int i=0;i<n;i++)
	{
		cin>>v[i];
	}
	int e=n;
	int x=0;
	while (k--)
	{
        int min=N;
		for(int i=0;i<e;i++)
		{
			if(min>v[i]) 
			{
				min=v[i];
			    x=i;
			}
		}
	    v[x-1]+=v[x];
		v[x+1]+=v[x];
		v.erase(v.begin()+x);
		e--;
	} 
	for(int i=0;i<e;i++)
	{
		cout<<v[i]<<" ";
	}
	cout<<endl;
	return 0;
}

优化: 模拟链表(便于删除中间节点):需要左右两个指针链接各个节点

优先队列:便于找到最值并且出队,相当于逻辑上删除该数下次不再比较这个数,但是缺点是不能实时更新//由于每删除一个数,其两边相邻数都要+1,因此,priority_queue里的数不一定是实时的,所以需要引入st\[\]存储更新,且在每次输出最小值时都要比较一下

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int N = 5e5 + 10;
int st[N], l[N], r[N];

signed main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int n, k; cin >> n >> k;
	priority_queue<pii, vector<pii>, greater<pii>>q;
	for(int i = 0; i < n; i ++)
	{
		cin >> st[i];
		q.push({st[i], i});
        l[i] = i - 1;//模拟链表,链接左右两侧节点 
		r[i] = i + 1;
		if(r[i] == n)
			r[i] = -1;
	}

	int cnt = k;
	while(k)
	{
		pii t = q.top();
        q.pop();

		if(t.first != st[t.second])
		{
			q.push({st[t.second], t.second});
			continue;
		}

		k --;
        int pos = t.second;
        //将该元素的相邻元素加上该数值
		if(l[pos] >= 0)
		    st[l[pos]] += t.first;
        if(r[pos] >= 0)
		    st[r[pos]] += t.first;
			//更新相邻点的相邻元素,模拟链表删除元素 
		if(l[pos] >= 0)
		    r[l[pos]] = r[pos];
		if(r[pos] >= 0)
		    l[r[pos]] = l[pos];
        //该元素已经被删除,打标记,方便最后输出结果 
		st[pos] = -1;
	}
	for(int i = 0; i < n; i ++)
	{
		if(st[i] != -1)
			cout << st[i] << " ";
	}
	cout << endl;
	return 0; 
}

优先队列:

priority_queue<pii, vector<pii>, greater<pii>>q;这里明确指出了vector是优先队列的底层容器,且存储的元素类型是pii,对于pair类型,greater<pii>是首先比较第一个元素,如果不同,则按照第一个元素排序,如果相同,则比较第二个元素。

priority_queue<数据类型> q; 默认是大顶堆,即从大到小排列;

priority_queue<数据类型,vector<数据类型>,greater<数据类型>> q;表示从大到小排列;

自定义排序:

相关推荐
To_OC16 小时前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
千纸鹤安安21 小时前
千问Qwen-AgentWorld来了:一个语言模型搞定七大Agent场景,GPT-5.4都输了
算法
七牛开发者1 天前
MCP 到底是什么?为什么 Agent 都想接上它
算法·aigc·agent
北域码匠1 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
kisshyshy1 天前
从递归到迭代,一文吃透二叉树的核心知识与 JavaScript 实现
javascript·算法·代码规范
To_OC2 天前
LC 49 字母异位词分组:想到哈希表很简单,选对 key 才是精髓
javascript·算法·leetcode
用户938515635072 天前
从 O(n²) 到 O(nlogn):一文读懂快速排序的“快”与“妙”
javascript·算法
To_OC2 天前
手写快排次次翻车?别死背快排模板了,这才是面试官想听的底层逻辑
javascript·算法·排序算法