解题思路:
数据为10e5 暴力n^2 肯定会超时
可以利用小根堆来做
注意事项:
由于value不断的加可能超过INT_MAX,所以value类型为long long
参考代码:
#include<iostream>
#include<vector>
using namespace std;
#include<queue>
#include<map>
typedef pair<long long, long long> pa_ir;
int main() {
int n, k;
cin >> n >> k;
vector<long long> arr(n + 2, 0);
map<int, pa_ir> idex;//map的key为元素的下标,而pa_ir来记录该以key为下标的前一个位置和后一个位置的下标
idex[0] = pa_ir(-1, 1);//来保障最小值为第一个值时可以向中间值一样操作
priority_queue<pa_ir, vector<pa_ir>, greater<pa_ir>> pri;//小根堆
for (int i = 1; i <= n; i++) {//将元素进数组和小根堆
long long x;
cin >> x;
arr[i] = x;
idex[i] = pa_ir(i - 1, i + 1);
pri.push(pa_ir(x, i));
}
idex[n + 1] = pa_ir(n, -1);//来保障最小值为最后一个值可以向中间值一样操作,即总体的map值比arr数组大2
while (k--) {
auto t = pri.top();
pri.pop();
//t.first != arr[t.second]来判断最小值是否更改,前一个出的会影响小根堆的值
if (t.first != arr[t.second]) {//当小根堆出去一个元素时,会影响周围的值,假设小根堆的第二个值是第一个小根堆的相邻值
//当第一个值出小根堆时会影响第二个的值,此时第二小的值会被该变,可能不会是最小值,此时再重新入小根堆,可保证最小值在堆顶
pri.push({ arr[t.second], t.second });
k++;
}
else {
int x = t.second;//删除元素的下标
arr[idex[x].first] += arr[x];//idex[x].first为下标为x的前一个元素
arr[idex[x].second] += arr[x];//idex[x].second为下标为x的后一个元素
//此时以x为元素的下标需要在map中删除,在此之前要更新map中元素的前后关系
idex[idex[x].first].second = idex[x].second;
idex[idex[x].second].first = idex[x].first;
//删除x
auto it = idex.find(x);
idex.erase(it);
}
}
此时map中it.second.second为最终留下的元素
for (auto it : idex) {
if (it.second.second == n + 1) break;
cout << arr[it.second.second] << " ";
}
return 0;
}0.0分
4 人评分
C语言网提供由在职研发工程师或ACM蓝桥杯竞赛优秀选手录制的视频教程,并配有习题和答疑,点击了解:
一点编程也不会写的:零基础C语言学练课程
解决困扰你多年的C语言疑难杂症特性的C语言进阶课程
从零到写出一个爬虫的Python编程课程
只会语法写不出代码?手把手带你写100个编程真题的编程百练课程
信息学奥赛或C++选手的 必学C++课程
蓝桥杯ACM、信息学奥赛的必学课程:算法竞赛课入门课程
手把手讲解近五年真题的蓝桥杯辅导课程
发表评论 取消回复