传送门ber~
容易发现选的每一段左右一定是同色…
那么有
其中
,
同色
若存在
且答案更优,即
斜率优化
单调栈
代码如下·:
#include<algorithm>
#include<cstring>
#include<ctype.h>
#include<cstdio>
#include<vector>
#define int long long
#define INF 2147483647
#define N 100020
using namespace std;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
typedef long long LL;
struct Data{
LL x,y;
Data(){}
Data(LL x,LL y):x(x),y(y){}
}tmp;
vector<Data>s[N];
int n,x,y,p,ans;
int cnt[N],pos[N],a[N],pre[N],top[N],f[N];
inline double Slope(Data a,Data b){
if(a.x==b.x) return a.y>b.y?-INF:INF;
return 1.0*(b.y-a.y)/(b.x-a.x);
}
main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
pre[i]=pos[a[i]];
pos[a[i]]=i;
cnt[i]=cnt[pre[i]]+1;
}
memset(pos,0,sizeof pos);
for(int i=1;i<=n;++i)
if(!pos[a[i]])
s[a[i]].push_back(Data(0,0)),pos[a[i]]=1;
for(int i=1;i<=n;i++){
p=a[i];
tmp=Data(2*p*cnt[i],f[i-1]+p*cnt[i]*cnt[i]-2*p*cnt[i]);
while(top[p]>1 && Slope(s[p][top[p]-1],s[p][top[p]])<=Slope(s[p][top[p]],tmp)) top[p]--,s[p].pop_back();
top[p]++;s[p].push_back(tmp);
while(top[p]>1 && Slope(s[p][top[p]-1],s[p][top[p]])<=cnt[i]) top[p]--,s[p].pop_back();
x=s[p][top[p]].x;y=s[p][top[p]].y;
f[i]=y-x*cnt[i]+p*cnt[i]*cnt[i]+p+2*p*cnt[i];
ans=max(ans,f[i]);
}
printf("%lld",ans);
return 0;
}