社区讨论

关于堆求区间中位数问题

P3466[POI 2008] KLO-Building blocks参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@lopty9qr
此快照首次捕获于
2023/11/08 22:03
2 年前
此快照最后确认于
2023/11/09 10:01
2 年前
查看原帖
建立4个堆来处理删除操作、求中位数
为什么题解中大根堆头就是中位数呢,如果区间长度为偶数中位数应该怎么取?有点不理解
代码无法过样例,求助qwq
CPP
#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
//#pragma GCC optimize("Ofast")
typedef long long ll;
typedef pair<int,int> pii;
#define mk(a,b) make_pair((a),(b))
#define int ll

const int maxn=5e5+10;
const int inf=1e12;
const int mod=1e9+7;
int n,m,k,ans=inf,sum=0,l,tot;
int a[maxn];

struct heap {
	int sum;
	priority_queue<int> q1,q2;
	inline void push(int x) {
		q1.push(x);
		sum+=x;
	};
	inline void erase(int x) {
		q2.push(x);
		sum-=x;
	};
	inline void clean() {
		while(!q2.empty()&&q1.top()==q2.top()) {
			q1.pop();
			q2.pop();
		}
	};
	inline void pop() {
		while(!q2.empty()&&q1.top()==q2.top()) {
			q1.pop();
			q2.pop();
		}
		if(!q1.empty()) {
			sum-=q1.top();
			q1.pop();
		}
	};
	inline int top() {
		while(!q2.empty()&&q1.top()==q2.top()) {
			q1.pop();
			q2.pop();
		}
		return q1.top();
	};
	inline int size() {
		return q1.size()-q2.size();
	};
	inline bool empty() {
		return (size()==0);
	};
};

heap pq1,pq2;

inline void balance() {
	pq1.clean();
	pq2.clean();
	while(pq1.size()>pq2.size()+1) {
		pq1.sum-=pq1.top();
		pq2.sum+=pq1.top();
		pq2.push(-pq1.top());
		pq1.pop();
	}
	while(pq1.size()<pq2.size()) {
		pq1.sum+=pq2.top();
		pq2.sum-=pq2.top();
		pq1.push(-pq2.top());
		pq2.pop();
	}
}

inline int read() {
	int s=0,w=1;
	char ch=getchar();
	while(!isdigit(ch)) {
		if(ch=='-') w=-1;
		ch=getchar();
	}
	while(isdigit(ch)) s=s*10+ch-'0',ch=getchar();
	return s*w;
}

inline void write(int x) {
	if(x<0) x=-x,putchar('-');
	if(x>9) write(x/10);
	putchar('0'+x%10);
}

signed main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	n=read(),k=read();
	for(int i=1; i<=n; ++i) a[i]=read();
	for(int i=1; i<=n; ++i) {
		if(!pq1.empty()&&a[i]>pq1.top()) {
			pq2.push(-a[i]);
			pq2.sum+=a[i];
		} else {
			pq1.push(a[i]);
			pq1.sum+=a[i];
		}
		balance();
		if(i>=k) {
			int mid=pq1.top();
			if(ans>abs(pq1.sum-pq2.sum-pq1.size()*mid+pq2.size()*mid)) {
				ans=abs(pq1.sum-pq2.sum-pq1.size()*mid+pq2.size()*mid);
				l=i-k+1;
				tot=mid;
			}
			if(pq1.top()>=a[i-k+1]) pq1.erase(a[i-k+1]);
			else pq2.erase(a[i-k+1]);
		}
	}
	write(ans),puts("");
	for(int i=1;i<=n;++i)
		if(i>=l&&i<=l+k-1) write(tot),puts("");
		else write(a[i]),puts("");
	return 0;
}

/*
5 3
3
9
2
3
1

out:
2
3
9
2
2
2

*/

回复

3 条回复,欢迎继续交流。

正在加载回复...