一、问题重述
给定N个整数的序列,进行K次操作:每次删除当前最小元素,并将其值加到相邻元素上。要求高效计算出最终序列。
二、完整代码解析(含详细注释)
#include <iostream>#include <vector>#include <queue>#include <set>using namespace std;// 定义链表节点结构struct Node {
long long value; // 存储节点值
int prev, next; // 前驱和后继指针
// 重载运算符用于set排序
bool operator<(const Node& other) const {
return value < other.value || (value == other.value && prev < other.prev);
}};int main() {
ios::sync_with_stdio(false); // 加速输入输出
cin.tie(nullptr);
int N, K;
cin >> N >> K; // 输入数字个数和操作次数
// 初始化双向链表(含哨兵节点)
vector<Node> nodes(N+2);
set<pair<long long, int>> min_heap; // 使用set模拟最小堆
// 构建初始链表和优先队列
for (int i = 1; i <= N; ++i) {
cin >> nodes[i].value;
nodes[i].prev = i-1;
nodes[i].next = i+1;
min_heap.insert({nodes[i].value, i}); // 存入值和位置
}
// 设置哨兵节点
nodes[0].next = 1; // 头哨兵
nodes[N+1].prev = N; // 尾哨兵
vector<bool> deleted(N+2, false); // 标记删除状态
// 执行K次删除操作
while (K--) {
auto it = min_heap.begin(); // 获取最小值
long long val = it->first;
int pos = it->second;
min_heap.erase(it);
// 处理前驱节点
int prev_pos = nodes[pos].prev;
if (prev_pos != 0) { // 如果不是头节点
min_heap.erase({nodes[prev_pos].value, prev_pos});
nodes[prev_pos].value += val; // 前驱节点增值
min_heap.insert({nodes[prev_pos].value, prev_pos});
}
// 处理后继节点
int next_pos = nodes[pos].next;
if (next_pos != N+1) { // 如果不是尾节点
min_heap.erase({nodes[next_pos].value, next_pos});
nodes[next_pos].value += val; // 后继节点增值
min_heap.insert({nodes[next_pos].value, next_pos});
}
// 更新链表指针
nodes[prev_pos].next = next_pos;
nodes[next_pos].prev = prev_pos;
deleted[pos] = true; // 标记删除
}
// 输出最终序列
int current = nodes[0].next; // 从第一个有效节点开始
while (current != N+1) {
cout << nodes[current].value << " ";
current = nodes[current].next;
}
return 0;}三、核心算法解析
数据结构设计:
双向链表维护元素间关系
set模拟最小堆实现高效取最小值
哨兵节点简化边界条件处理
关键操作流程:
复杂度分析:
时间复杂度:O(KlogN)(每次堆操作logN)
空间复杂度:O(N)(存储链表和堆)
四、常见问题解答
Q:为什么用set而不用priority_queue? A:set支持快速查找和删除任意元素,priority_queue只能访问堆顶
Q:如何处理相同最小值的冲突? A:通过自定义比较函数,当值相同时按位置排序
Q:哨兵节点有什么作用? A:统一处理头尾节点的边界情况,避免额外条件判断
来源:编程学习
點擊查看更多內容
為 TA 點贊
評論
評論
共同學習,寫下你的評論
評論加載中...
作者其他優質文章
正在加載中
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
