Description:
有N(1<=N<=40000)个奶牛到FJ的餐厅吃饭,餐厅里有M(1<=M<=N)种菜,每头牛有自己喜欢的菜的编号P_i(1<=P_i<=M),每头牛只吃自己喜欢的这道菜。
牛儿们在外面排着队进来,按照排队顺序一批一批进来,每批可以同时进来任意头牛,每一批吃完(注意包括最后一批)都要进行打扫,如果这批牛中一共需要K种菜,那么吃完后的打扫时间为K*K。
请你帮助FJ如何安排各批次使得总打扫时间最少。
Input
第1行:空格隔开的两个整数N和M
第2到N+1行:第i+1行包含一个整数P_i。
Output
输出最少打扫时间。
Solution
又是一个神奇的DP.
使用了神奇的DP式.
已知
Ans≤n
.
This
is
very
important!!!
我们一起可以选
x(1≤x≤n)
头牛一起进餐,若不同的色数为
j
个,则花费
由此可知,
j≤x√
才是优的,否则花费会大于
n
.
因此,我们可以这样做:
设
可得DP式:
那么问题来了,如何维护
P
呢?
详见下面代码
范围:
1≤j≤n√+1
初值:
详见下面代码
Program
uses
math;
var
x,n,m,i,j,k,ml:longint;
f,p,l:array [-1..40000] of longint;
begin
assign(input,'cleanup.in');
assign(output,'cleanup.out');
reset(input);
rewrite(output);
readln(n,m);
ml:=trunc(sqrt(n))+1;
fillchar(l,sizeof(l),255);
readln(x);
l[x]:=1;
f[1]:=1;
p[1]:=1;
f[-1]:=maxlongint div 2;
for i:=2 to n do
begin
readln(x);
p[0]:=i;
for j:=ml downto 1 do
if l[x]<p[j] then
p[j]:=p[j-1];
f[i]:=i;
for j:=1 to ml do
f[i]:=min(f[i],f[p[j]-1]+j*j);
l[x]:=i;
end;
writeln(f[n]);
close(input);
close(output);
end.