【蓝桥杯 2023 C++ 省 B】H - 整数删除 补题
【蓝桥杯 2023 C++ 省 B】H - 整数删除 补题
题意
给一个数列,然后操作K次,每次删除最小的那个,并且把它相邻的数字都加上它的值
思路
用优先队列加双链表
-
优先队列
可以在每次操作时,快速找到中最小的那个数字,取出来操作
用tuple<long long, int>,前面是val,后面是这个数字在原数列中对应的id,方便操作它相邻的数字
-
双链表
搞两个数组,front和back,一个连前一个数字,一个连后一个数字
更新优先队列中的数值
在每次操作的时候,都有可能会对其他数字造成影响,原本在已经在优先队列中的那个最小值,可能被操作完之后,就不是最小的那个数字了。
所以在每次取出数字的时候,都要看当前拿出来的状态,是不是已经被修改完了的
于是建立另一个数组来记录当前拿出来的这个数字,拿出来的时候,是不是可以操作了
modify
- -1说明这个数字已经被删除
- 0说明这个数字已经是可以被操作(删除的状态)
- 大于0说明这个数字还需要被修改,还不是最小值
代码
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <tuple>
using namespace std;
// tuple前面是val,后面是id
typedef tuple<long long, long long> TII;
const int N = 5e5 + 5;
// 双向链表加优先队列
priority_queue<TII, vector<TII>, greater<TII>>q;
// 双链表
int front[N], back[N];
// 标记数组(已经被删除,还是还不能操作,需要修改多少)
long long modify[N];
// 数列数组
long long a[N];
int n, k;
// 读入
void init() {
cin >> n >> k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
// 每一个数都在开始的时候推入队列
q.push({ a[i],i });
// 建立双链表(链表里面装的是id)
front[i] = i - 1; // 前驱
back[i] = i + 1; // 后继
}
}
void solve() {
int f, b, id;
int cnt = 0;
long long val;
while (cnt < k) { // 操作k次,有效操作才让cnt++
tie(val, id) = q.top(); // tie获取数据,C++11好像不能auto[val,id]
q.pop();
if (modify[id] == -1)continue; // 已经被删除了,不操作
// 需要被修改之后重新推入队列,这一次拿出来的是无效的,扔掉
if (modify[id]) {
a[id] += modify[id]; // 在原数组上面修改,最后输出数组就行
modify[id] = 0; // 修改值归零
q.push({ a[id],id }); // 重新加入队列当中
continue; // 不删除,continue
}
modify[id] = -1; // 有效操作,删除数字就把modify改成-1
f = front[id]; b = back[id]; // 取出前驱、后继节点的id
modify[f] += val; // 做出修改
modify[b] += val;
back[f] = b; // 删除中间那个节点的时候,记得连接前驱后继
front[b] = f;
cnt++; // 有效删除,cnt++
}
// 队列非空,有些数字需要被修改,但是还没修改,继续操作一下
while (!q.empty()) {
tie(val, id) = q.top();
q.pop();
if (modify[id]) { // 修改
a[id] += modify[id];
modify[id] = 0;
}
}
for (int i = 1; i <= n; i++) { // 遍历数组,看哪个数字没被删除,就输出
if (modify[i] != -1) {
cout << a[i] << " ";
}
}
}
int main() {
init();
solve();
return 0;
}
反思
VP的时候看到这题还是很有感觉的,但是细想又觉得有点麻烦,实际已经想到优先队列加上链表了,觉得每次操作完之后,最小的数字可能会发生改变,又想不到用什么来维护(modify),于是乎就没写了,还是得动手写写

浙公网安备 33010602011771号