[NOI2010] 超级钢琴

一个很经典的做法。
\(k\)个最值的求法,先对每个元素进行最操作,再对堆顶进行次操作丢入堆。
考虑怎么进行次操作。

每次把可操作的区间按最操作的位置切开。

#include<iostream>
#include<cstdio>
#include<queue>
#define ll long long 
#define N 500005

inline ll read(){
	ll ans = 0,f = 1;
	char a = getchar();
	while((a != '-') && !(a <= '9' && a >= '0'))
	a = getchar();
	if(a == '-')
	f = -1,a = getchar();
	while(a <= '9' && a >='0')
	ans = (ans << 3) + (ans << 1) + (a - '0'),a = getchar();
	return ans * f;
}

ll num[N],sum[N];
ll n,k,l,r;

ll v[N << 2];
ll s[N << 2];

struct P{
	int li,ri,t,x,v;
};

std::priority_queue<P>QWQ;

bool operator < (P a,P b){
	return a.v < b.v;
}

#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)

inline void build(int u,int l,int r){
	if(l == r){
		v[u] = sum[l];
		s[u] = l;
		return ;
	} 
	build(ls(u),l,mid);
	build(rs(u),mid + 1,r);
	v[u] = std::min(v[ls(u)],v[rs(u)]);
	if(v[u] == v[ls(u)])
	s[u] = s[ls(u)];
	else
	s[u] = s[rs(u)];
}

inline ll q(int u,int l,int r,int tl,int tr){
	if(tl <= l && r <= tr)
	return u;
	ll ans1 = 0 , ans2 = 0;
	if(tl <= mid)
	ans1 = q(ls(u),l,mid,tl,tr);
	if(tr > mid)
	ans2 = q(rs(u),mid + 1,r,tl,tr);
	if(v[ans1] < v[ans2])
	return ans1;
	else
	return ans2;
}


int main(){
	v[0] = 1e18;
	scanf("%lld%lld%lld%lld",&n,&k,&l,&r);
	for(int i = 1;i <= n;++i)
	num[i] = read(),sum[i] = sum[i - 1] + num[i];
	build(1,0,n);
	for(int i = l;i <= n;++i){
		P a;
		a.li = std::max((ll)0,i - r);
		a.ri = i - l;
		a.t  = s[q(1,0,n,a.li,a.ri)];
		a.x = i;
		a.v = sum[i] - sum[a.t];
		QWQ.push(a);
	}
//	for(int i = 1;i <= n;++i)
//	std::cout<<sum[i]<<" ";
//	puts("");
	ll ans = 0;
	for(int i = 1;i <= k;++i){
		P a = QWQ.top();
		QWQ.pop();
		ans += a.v;
		P b;
		b.li = a.li; 
		b.ri = a.t - 1;
		if(b.li <= b.ri){
			b.t = s[q(1,0,n,b.li,b.ri)];
			b.x = a.x;
			b.v = sum[b.x] - sum[b.t];
			QWQ.push(b);
		}
		b.li = a.t + 1; 
		b.ri = a.ri;
		if(b.li <= b.ri){
			b.t = s[q(1,0,n,b.li,b.ri)];
			b.x = a.x;
			b.v = sum[b.x] - sum[b.t];
			QWQ.push(b);
		}		
	}
	std::cout<<ans<<std::endl;

posted @ 2021-08-04 14:49  fhq_treap  阅读(42)  评论(0编辑  收藏  举报