[BZOJ4709][JSOI2011]柠檬(斜率优化DP)

显然选出的每一段首尾都是相同的,于是直接斜率优化,给每个颜色的数开一个单调栈即可。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 6 typedef long long ll;
 7 using namespace std;
 8 
 9 const int N=100010;
10 ll n,ans,a[N],f[N],lst[N],top[N],cnt[N];
11 struct P{ ll x,y; };
12 vector<P>s[N];
13 
14 bool Cmp(P a,P b,P c){ return (b.y-a.y)*(c.x-b.x)<=(c.y-b.y)*(b.x-a.x); }
15 
16 int main(){
17     freopen("bzoj4709.in","r",stdin);
18     freopen("bzoj4709.out","w",stdout);
19     scanf("%lld",&n);
20     rep(i,1,n) scanf("%lld",&a[i]),cnt[i]=cnt[lst[a[i]]]+1,lst[a[i]]=i;
21     rep(i,1,n) if (s[a[i]].size()==0) s[a[i]].push_back((P){0,0});
22     rep(i,1,n){
23         int p=a[i]; P tmp=(P){2*p*cnt[i],f[i-1]+p*cnt[i]*cnt[i]-2*p*cnt[i]};
24         while (top[p]>1 && Cmp(s[p][top[p]-1],s[p][top[p]],tmp)) top[p]--,s[p].pop_back();
25         top[p]++; s[p].push_back(tmp);
26         while (top[p]>1 && (s[p][top[p]].x-s[p][top[p]-1].x)*cnt[i]>=s[p][top[p]].y-s[p][top[p]-1].y)
27             top[p]--,s[p].pop_back();
28         f[i]=s[p][top[p]].y-s[p][top[p]].x*cnt[i]+p+2*p*cnt[i]+p*cnt[i]*cnt[i]; ans=max(ans,f[i]);
29     }
30     printf("%lld\n",ans);
31     return 0;
32 }

 

posted @ 2018-10-22 23:44  HocRiser  阅读(184)  评论(0编辑  收藏  举报