把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P2034 选择数字

题面传送门

对于这道题,简单粗暴的\(dp\)是不难想的,\(dp\)方程式为\(f_i=max(f_{j-1}+\sum_{s=j+1}^ia_s)\),其中\(max(i-k,0)\leq j\leq i-1\),然后就有了\(70\)

代码实现:

#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
long long n,k,a[500039],sum[500039],q[500039],head,tail,f[500039],ans,tot,pus;
int main(){
	register int i,j,s;
	scanf("%lld%lld",&n,&k);
	for(i=1;i<=n;i++)scanf("%lld",&a[i]);
	f[1]=a[1];
	for(i=2;i<=n;i++){
		for(j=max(i-k,0);j<=i-1;j++){
			ans=0;
			for(s=j+1;s<=i;s++) ans+=a[s];
			f[i]=max(f[i],ans+f[j-1]);
		}
		f[i]=max(f[i],f[i-1]);
		tot=max(tot,f[i]);
	}
	printf("%lld\n",tot);
}

考虑前缀和优化,设\(sum\)为预处理数组,\(dp\)方程式变为\(f_i=max(f_j+sum_i-sum_j)\),可以有\(80\)分。
代码实现:

#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
long long n,k,a[500039],sum[500039],q[500039],head,tail,f[500039],ans,tot,pus;
int main(){
	register int i,j,s;
	scanf("%lld%lld",&n,&k);
	for(i=1;i<=n;i++)scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
	f[1]=a[1];
	for(i=2;i<=n;i++){
		for(j=max(i-k,0);j<=i-1;j++){
			f[i]=max(f[i],sum[i]-sum[j]+f[j-1]);
		}
		f[i]=max(f[i],f[i-1]);
		tot=max(tot,f[i]);
	}
	printf("%lld\n",tot);
}

我们注意到\(j\)这一重循环在反复寻找区间最值,那么想到可以单调队列优化,这么一看,似乎是单调队列板子题:维护一个单调队列,每次让\(f_{i-2}+a_i\)入队并维护单调性,设q为单调队列,那么状态转移方程:
\(f_i=max(f_{i-1},f_{q_{head+1}-1}+sum_i-sum_{q_{head+1}})\)
代码实现:

#include<cstdio>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
long long n,k,a[500039],sum[500039],q[500039],head,tail,f[500039],ans,tot,pus;
int main(){
	register int i,j,s;
	scanf("%lld%lld",&n,&k);
	for(i=1;i<=n;i++){
		scanf("%lld",&a[i]);sum[i]=sum[i-1]+a[i];
	}
	f[1]=a[1];
	q[++tail]=0;
	for(i=2;i<=n;i++){
		while(head!=tail&&i-q[head+1]>k) head++;
		while(head!=tail&&f[q[tail]-1]+sum[i]-sum[q[tail]]<f[i-2]+a[i]) tail--;
		q[++tail]=i-1;
		f[i]=max(f[q[head+1]-1]+sum[i]-sum[q[head+1]],f[i-1]);
		tot=max(tot,f[i]);
	}
	//for(i=1;i<=n;i++) printf("%lld\n",f[i]);
	printf("%lld\n",tot);
}
posted @ 2020-03-14 10:11  275307894a  阅读(53)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end