超级钢琴

题意

给定一个序列,定义和弦为长度在[L,R]上的连续元素集,其值为元素和。求最大的前k个和弦值之和。


思路

暴力思路是显然的:枚举左端点,然后依次枚举右端点得到最大值。

考虑优化:对于每一个左端点,能得到的最大值应该为$$max{sum[j]}-sum[chosen_point]$$

求最大值的过程可以使用st表优化,然后放到堆里即可。

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

	template<typename T>inline void read (T &x) {
		x=0;T f=1;char c=getchar();
		for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
		for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
		x*=f;
	}

	template<typename T>inline void write (T x) {
		if (x<0) putchar('-'),x*=-1;
		if (x>=10) write(x/10);
		putchar(x%10+'0');
	}

}

using namespace StandardIO;

namespace Project {
	#define int long long
	
	const int N=500500;
	
	int n,k,L,R,ans;
	int st[N][20];
	int sum[N];
	struct node {
		int val,lpos,rpos,r;
		node () {}
		node (int _v,int _l,int _r,int _rr) : val(_v),lpos(_l),rpos(_r),r(_rr) {}
		friend inline bool operator < (const node x,const node y) {
			return x.val<y.val;
		}
	};
	priority_queue<node> q;
	
	inline int min (int a,int b) {
		return (sum[a]<sum[b])?a:b;
	}
	inline int query (int l,int r) {
		if (l>r) return -1;
		int x=log2(r-l+1);
		return min(st[l][x],st[r-(1<<x)+1][x]);
	}

	inline void MAIN () {
		read(n),read(k),read(L),read(R);
		for (register int i=1; i<=n; ++i) {
			read(sum[i]),sum[i]+=sum[i-1],st[i][0]=i;
		}
		for (register int i=1; (1<<i)<=n; ++i) {
			for (register int j=0; (1<<i)+j-1<=n; ++j) {
				st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
			}
		}
		for (register int i=L; i<=n; ++i) {
			int tmp=query(max(0ll,i-R),i-L);
			q.push(node(sum[i]-sum[tmp],max(i-R,0ll),i-L,i));
		}
		for (register int i=1; i<=k; ++i) {
			node now=q.top();q.pop(),ans+=now.val;
			int tmp=query(now.lpos,now.rpos),s=query(now.lpos,tmp-1),t=query(tmp+1,now.rpos);
			if (s!=-1) q.push(node(sum[now.r]-sum[s],now.lpos,tmp-1,now.r));
			if (t!=-1) q.push(node(sum[now.r]-sum[t],tmp+1,now.rpos,now.r));
		}
		write(ans);
	}
	
	#undef int
}

int main () {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	Project::MAIN();
}

posted @ 2019-09-15 11:12  Ilverene  阅读(140)  评论(0编辑  收藏  举报