BZOJ 4709 柠檬
注意到一个最优区间的 s0==区间的开头 && s0==区间的结尾,那么我们有个N^2的dp。
f[i]=max(f[j-1]+a[i]*(s[i]-s[j]+1)^2)。
注意到单调性,在栈上二分答案。
#include<bits/stdc++.h> #define Max(a,b) (a>b?a:b) using namespace std; template <class T> inline void read(T &x){ static char c; for (c=getchar();!isdigit(c);c=getchar()); for (x=0;isdigit(c);c=getchar())x=x*10+c-48; } #define N 100007 #define Mid (l+r>>1) int n,a[N],x,net[N],last[N],now,tot,k[N]; vector<int> sta[N]; long long f[N]; int cal(int x,int y){ int l=1,r=n,ret=n+1; while (l<=r) { if (f[x-1]+1ll*a[x]*(Mid-k[x]+1)*(Mid-k[x]+1)>=f[y-1]+1ll*a[y]*(Mid-k[y]+1)*(Mid-k[y]+1)) { ret=Mid; r=Mid-1; } else l=Mid+1; } return ret; } signed main () { // freopen("lemon.in","r",stdin); // freopen("lemon.out","w",stdout); read(n); for (int i=1;i<=n;i++) { read(x); a[i]=x; k[i]=k[last[x]]+1; net[last[x]]=i; last[x]=i; } for (int i=1;i<=n;i++) { x=a[i]; while (sta[x].size()>1&&cal(sta[x][sta[x].size()-2],sta[x][sta[x].size()-1]) <=cal(sta[x][sta[x].size()-1],i)) sta[x].pop_back(); sta[x].push_back(i); while (sta[x].size()>1&&cal(sta[x][sta[x].size()-2],sta[x][sta[x].size()-1]) <=k[i]) sta[x].pop_back(); int ed=sta[x][sta[x].size()-1]; f[i]=f[ed-1]+1ll*x*(k[i]-k[ed]+1)*(k[i]-k[ed]+1); } printf("%lld\n",f[n]); }