2019-CSP-S划分

划分

m y y myy myy证明
这道题其他博客已经讲的很清楚了,就是发现这个转移满足单调性然后能满足后面的一定满足前面。
主要讲讲为什么单调队列的转移为什么是 q [ l + 1 ] q[l+1] q[l+1]而不是 q [ l ] q[l] q[l],由这道题目转移的性质,我们要把这道题决策点的转移尽量卡满(能靠右一定要靠右),那如果满足单调队列里队头决策点的下一个决策点能转移,那么当前队头决策点就一定能被弹掉。如果 q [ l ] q[l] q[l]被弹掉了 q [ l + 1 ] q[l+1] q[l+1]不一定能满足,那么这道题单调队列转移就会出问题。同时 q [ l + 1 ] q[l+1] q[l+1] q [ l ] q[l] q[l]更靠近 i i i(单调队列里保存的决策最优点保存的是下标),那么前者构成的前缀和一定比后者更小,如果这样能满足转移条件的话才能保证一定是最优决策。
88 p t s 88pts 88pts代码,反正高精我在考场上想出来了多半也没时间写

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+50;
int n,type,l=0,r=0,sum[N],q[N],pre[N],dp[N];
int x;
inline int read(){
	int cnt=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-f;c=getchar();}
	while(isdigit(c)){cnt=(cnt<<1)+(cnt<<3)+(c^48);c=getchar();}
	return cnt*f;
}
inline int val(int pos){return 2*sum[pos]-sum[pre[pos]];}
signed main(){
	n=read(),type=read();
	for(int i=1;i<=n;++i) x=read(),sum[i]=sum[i-1]+x;
	q[++r]=0;
	for(int i=1;i<=n;++i){
		while(l<r&&val(q[l+1])<=sum[i]) ++l;
		pre[i]=q[l];
		dp[i]=dp[pre[i]]+(sum[i]-sum[pre[i]])*(sum[i]-sum[pre[i]]);
		while(l<=r&&val(i)<=val(q[r]))--r;
		q[++r]=i;
	}
	cout<<dp[n]<<endl;
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值