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\)一样,我们列出不等式:
然后整理一下可以得到:
之后的事情就十分简单了,套用斜率优化的板子就行了。
话说看了黄学长的博客发现还有把\(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;
}
「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」