#include <bits/stdc++.h>
#define endl '\n'
typedef long long ll;
using namespace std;
//数据结构在这里定义
const int N =1e5+5;
int n,k;
ll A[N];//存原数组的值
int L[N],R[N]={1};
//左右数组用于O(1)复杂度获取某个元素的前后元素
//同时O(1)复杂度删除该元素
struct node{
int idx;
int val;
node(int idx, int val):idx(idx),val(val) {}
//小顶堆重载>里面也是>
bool operator>(const node& other) const{
return val==other.val?idx>other.idx:val>other.val;
}
};
//每次从堆顶拿一个元素就是题目要删除的
priority_queue<node, vector<node>, greater<node>> pq;
void solve(){
//cin cout在这里
cin >> n >> k;
for(int i = 1 ; i <= n; i++){
cin >> A[i];
L[i] = i - 1;
R[i] = i + 1;
pq.push(node(i, A[i]));
}
// while(!pq.empty()){
// node cur = pq.top(); pq.pop();
// printf("A[%d] = %d\n",cur.idx,cur.val);
// }
// for(int i = R[0];i<=n;i=R[i]){
// cout << A[i] << " ";
// }
while(1){
node cur = pq.top(); pq.pop();
//有可能这个结点是旧结点,之前的删除操作改变了其值
if(A[cur.idx] != cur.val) continue;
//在模拟双向链表上删除结点,并修改左右结点的值
//0和n+1视为特殊边界
if(L[cur.idx] >= 1){//说明有左结点
// R[L[cur.idx]] = R[cur.idx];
A[L[cur.idx]] += cur.val;
//更新后的结点需要重新进入队列,重新排列
pq.push(node(L[cur.idx], A[L[cur.idx]]));
}
if(R[cur.idx] <= n){
// L[R[cur.idx]] = L[cur.idx];
A[R[cur.idx]] += cur.val;
pq.push(node(R[cur.idx], A[R[cur.idx]]));
}
//操作完一次 k--
//这个链表更新操作不能放到上面的if里
//不管左右还有没有结点都得更新
//这样才能正确的指向 0 和 n+1表示这是最后一个元素了
R[L[cur.idx]] = R[cur.idx];
L[R[cur.idx]] = L[cur.idx];
k--;
if(k==0) break;
}
for(int i = R[0]; i <= n; i = R[i]){
cout << A[i] << " ";
}
cout << endl;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t;//多组数据要cin
//cin >> t;
t = 1;
while(t--){
solve();
}
return 0;//必须加return 0
}
0 回复
0 转发
0 喜欢
5 阅读



