bzoj 4709 [ Jsoi2011 ] 柠檬 —— 斜率优化DP

题目: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;
}

 

posted @ 2018-07-21 19:47  Zinn  阅读(198)  评论(0编辑  收藏  举报