题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4709
课上讲的题,还是参考了博客...:https://www.cnblogs.com/GXZlegend/p/8615607.html
这道题和之前写的斜率优化不同的一点是用单调栈维护上凸壳,而且需要二分查找答案;
为什么感觉每次写出来的斜率优化DP都不一样...还是没有理解透彻...
代码如下:
#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;typedef long long ll;int const maxn=1e5+5,maxm=1e4+5;int n,a[maxn];ll s[maxn],cnt[maxm],f[maxn];vector<int>v[maxm];ll x(int i){return s[i]-1;}ll y(int i){return f[i-1]+a[i]*(s[i]-1)*(s[i]-1);}ll ans(int i,int j){return f[j-1]+a[i]*(s[i]-s[j]+1)*(s[i]-s[j]+1);}ll squ(ll x){return x*x;}int main(){ ???scanf("%d\n",&n); ???for(int i=1,j,k,t;i<=n;i++) ???{ ???????scanf("%d",&a[i]); s[i]=++cnt[a[i]]; ???????while((t=v[a[i]].size()-1)>0 && ??????????(x(i)-x(j=v[a[i]][t]))*(y(k=v[a[i]][t-1])-y(j)) - (y(i)-y(j))*(x(k)-(x(j))) > 0)//别写成if ????????????v[a[i]].pop_back(); ???????v[a[i]].push_back(i); ???????int l=1,r=v[a[i]].size()-1,res=0;//res=0 ?//不取新加入的i ????????while(l<=r) ???????{ ???????????int mid=((l+r)>>1); ???????????if(ans(i,v[a[i]][mid])>ans(i,v[a[i]][mid-1]))res=mid,l=mid+1; ???????????else r=mid-1; ???????} ???????f[i]=ans(i,v[a[i]][res]); ???} ???printf("%lld\n",f[n]); ???return 0;}
bzoj 4709 ?[ Jsoi 2011 ] 柠檬 ——斜率优化DP
原文地址:https://www.cnblogs.com/Zinn/p/9347760.html