Orz w_yqts
卡了18次,终于rank1了…
f[i]表示以i为结尾的最小代价
f[i]最大为i(每个点单独一段)
f[i]=min{f[j]+cnt(j+1~i)^2}
若cnt(j+1~i)^2>i就可以退出了.
若存在相同数字可以用链表删除.
大概是O(n^3/2)的.
#include <cstdio>
#define N 40005
inline int read()
{
char ch=getchar();
int x=0;
while ('0'>ch || ch>'9') ch=getchar();
while ('0'<=ch && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x;
}
inline int min(int a,int b) {return a<b?a:b;}
int a[N],f[N],Next[N],sqr[N];
int n,m;
int main()
{
n=read(),m=read();
for (int i=1;i<=n;++i)
{
a[i]=read();
Next[i]=i-1;
sqr[i]=sqr[i-1]+(i<<1)-1;
f[i]=i;
}
for (int i=2;i<=n;++i)
{
int j=i-1,pre=i,tot=1;
while (sqr[tot]<f[i] && j)
{
f[i]=min(f[i],f[j]+sqr[tot]);
if (a[j]==a[i]) Next[pre]=Next[j];
else ++tot,pre=j;
j=Next[j];
}
if (j)
{
if (a[j]==a[i]) Next[pre]=Next[j];
else pre=j;
j=Next[j];
}
}
printf("%d\n",f[n]);
}