JZOJ 5409 Fantasy & NOI 2010 超级钢琴 题解

其实早在 2020-12-26 的比赛我们就做过 5409. Fantasy

这可是紫题啊

题目大意

给你一个序列,求长度在 \([L,R]\) 区间内的 \(k\) 个连续子序列的最大和

题解

如此多的子序列并不好处理

\(i\) 为一个区间的左端点,那么右端点的区间为 \([i+L-1,i+R-1]\) ,记前缀和为 \(sum_i\)

那么一个区间 \([i,j]\) 的和就是 \(sum_j-sum_{i-1}\) 已经知道左端点 \(sum_i\) ,只要找到最大的 \(sum_j\) 即可

所以可以用 \(\text{RMQ}\) 来解决查找问题。考虑把一个区间变成四元组 \(\{now,l,r,id\}\)

表示左端点 \(i\) 的位置,右端点的区间,区间 \([l,r]\)\(j\) 的位置 。将一些四元组放入堆中

每次将堆顶的拆成两个 \(\{now,l,id-1,id_1\},\{now,pos+1,r,id_2\}\)

再放进堆中,原堆顶删除。\(id_1,id_2\) 都是 \(\text{RMQ}\) 实现,每次堆顶的值 \(sum_{id}-sum_{now-1}\) 的和就是答案

Code

#include<bits/stdc++.h>
using namespace std;
char buf[100000],*S=buf,*T=buf;
inline char Gc() {
	return S==T&&(T=(S=buf)+fread(buf,1,100000,stdin),S==T)?EOF:*S++;
}
inline int Rd() {
	register int o=0,f=0;
	static char c=Gc();
	for(;c<'0'||c>'9';c=Gc()) f|=c==45;
	for(;c>'/'&&c<':';c=Gc()) o=(o<<1)+(o<<3)+(c^48);
	return f?-o:o;
} 
const int N=500005;
typedef long long LL;
int n,K,L,R,pw[35]={1},lg[N],sum[N],f[N][35];
LL ans;
inline int maxx(int x,int y) { return sum[x]>sum[y]?x:y; }
inline int RMQ(int l,int r) {
	register int k=lg[r-l+1];
	return maxx(f[l][k],f[r-pw[k]+1][k]);
}
struct node {
	int x,l,r,id; node() { }
	inline node(int _x,int _l,int _r):x(_x),l(_l),r(_r),id(RMQ(_l,_r)) { }
	inline bool operator<(const node &o) const {
		return sum[id]-sum[x-1]<sum[o.id]-sum[o.x-1]; }
}oo;
priority_queue<node>heap;
int main() {
//	freopen("fantasy.in","r",stdin);
//	freopen("fantasy.out","w",stdout);
	for(int i=1;i<31;i++)pw[i]=pw[i-1]<<1;
	n=Rd(),K=Rd(),L=Rd(),R=Rd();
	for(int i=1;i<=n;i++)f[i][0]=i,sum[i]=sum[i-1]+Rd();
	for(int i=2;i<=n;i++)lg[i]=lg[i>>1]+1;
	for(int j=1;j<=lg[n];j++)
		for(int i=0;i+pw[j-1]-1<=n;i++)
			f[i][j]=maxx(f[i][j-1],f[i+pw[j-1]][j-1]);
	for(int i=1;i<=n;i++)
		if(i+L-1<=n)
			heap.push(node(i,i+L-1,min(i+R-1,n)));
	while(K--) {
		oo=heap.top(),heap.pop(),ans+=1LL*sum[oo.id]-1LL*sum[oo.x-1];
		if(oo.l^oo.id)heap.push(node(oo.x,oo.l,oo.id-1));
		if(oo.id^oo.r)heap.push(node(oo.x,oo.id+1,oo.r));
	}
	printf("%lld",ans);
}
原文地址:https://www.cnblogs.com/KonjakLAF/p/14588861.html