[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 }