返回题解分享
讨论 / 题解分享/ 帖子详情

整数删除(编程题) - 题解

#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 阅读
回复 (0)
默认 最新
暂无回复,快来抢沙发!