BZOJ3156 防御准备

BZOJ3156 防御准备

题目传送门

题解

这道\(Dp\)题目也算是比较清真了吧,看到数据范围其实就差不多可以知道是个斜率优化\(Dp\)了。我们比较容易地可以写出转移方程:\(dp[i]=max(dp[j]+\sum_{k=j+1}^{i-1}(i-k))+a[i] \Rightarrow dp[i]=max(dp[j]+\sum_{k=j+1}^{i-1}i-\sum_{k=j+1}^{i-1}k)+a[i])\) \(\Rightarrow dp[i]=max(dp[j]+(i-j-1)*i+\frac{(j+i)*(i-j-1)}{2})\)。然后还是像斜率优化\(Dp\)一样,我们列出不等式:

$dp[j]+(i-j-1)*i+\frac{(j+i)*(i-j-1)}{2}\geq dp[k]+(i-k-1)*i+\frac{(k+i)*(i-k-1)}{2}$($j

然后整理一下可以得到:

$\frac{f[k]-f[j]+k^2-j^2+k-j}{2*(k-j)}\leq i$

之后的事情就十分简单了,套用斜率优化的板子就行了。
话说看了黄学长的博客发现还有把\(a[i]\)反过来读入的方法。。表示有点不理解这个方法啊。。

code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int maxn=1e6+500;
int n;
ll a[maxn],f[maxn];
ll que[maxn],l,r;
/*==================Define Area================*/
double Cal(ll j,ll k) {
	return (double)(2*(f[k]-f[j])+k*k-j*j+k-j)/(k-j);
}

int main() {
	read(n);
	for(int i=1;i<=n;i++) {
		read(a[i]);
	}
	for(int i=1;i<=n;i++) {
		while(l<r&&Cal(que[l],que[l+1])<2*i) l++;
		int t=que[l];
		f[i]=f[t]+(i-t)*(i-t-1)/2+a[i];
		while(l<r&&Cal(que[r-1],que[r])>Cal(que[r],i)) r--;
		que[++r]=i; 
	}
	printf("%lld\n",f[n]);
	return 0;
}
posted @ 2018-08-10 08:54  Apocrypha  阅读(118)  评论(0编辑  收藏  举报