打扫卫生
题意:一段序列,分为若干段,每段分值为该段中不同数字个数平方,求划分方案使分值和最小。
分析:n^2DP很好写 f[i]:=min(f[j]+cost[i+1,j]); 考虑优化,由于任何序列其最小分值和最大为n(每个元素自成一段),故可推出最优方案中,每段分值不可能超过n,也就是不同元素个数不超过根号n,故方程改为f[i]:=min(f[b[j]]+j*j); j<=√n; b[j]表示一个位置编号,意思是从i开始到b[j]+1,共有j个不同的数字,然后维护即可。
program cleanup; var f,a,b,c,hash:array[0..100000]of int64; n,m,t:int64; i,j:longint; function min(x,y:longint):longint; begin if x<y then min:=x else min:=y; end; begin readln(n,m); for i:=0 to m do hash[i]:=0; for i:=1 to n do read(a[i]); m:=trunc(sqrt(n)); f[0]:=0; for i:=1 to n do begin f[i]:=maxlongint; for j:=1 to m do if hash[a[i]]<=b[j] then inc(c[j]); hash[a[i]]:=i; for j:=1 to m do if c[j]>j then begin t:=b[j]+1; while hash[a[t]]>t do inc(t); b[j]:=t; dec(c[j]); end; for j:=1 to m do f[i]:=min(f[i],f[b[j]]+j*j); end; writeln(f[n]); end.
时间: 2024-10-11 11:42:33