解题报告 QUE
即 usaco Mar 09 Cleaning Up
【转】
题意Overview:
有N头奶牛,每头那牛都有一个标号Pi,1 <= Pi <= M <= N <= 40000。 现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k。那总的不河蟹度就是所有段的不河蟹度的总和。
题解Solution:
直观就会有一个N^2的DP。
首先是如果把它们切成N段的话,答案上界是N。所以如果某[i, j]段kN−− ,这肯定不是最优解的一部分,可以break。
用diff[i, j]表示[i, j]间不同的数的数目。
决策到f[i]时,若k < j, 且有diff[k, i] == diff[j, i],那么直接skip掉j直接跳到k。
不要忽略一个很显然的东西:有diff[k, i] == diff[j, i],就必然有diff[k, i'] == diff[k, i']。(i < i')。也就是f[k -1]总是比f[j -1]优的T_T。
const
MaxN = 40001;
var
idx, appear, a, f: array[0..MaxN] of longint;
i, j, k, n, m, lim, orz: longint;
function min(a, b: longint): longint;
begin
if a < b then exit(a) else exit(b);
end;
begin
assign(input, '1584.in'); reset(input);
assign(output, '1584.out'); rewrite(output);
read(n, m);
for i:= 1 to n do
begin
read(a[i]);
appear[i]:= -1;
end;
lim:= trunc(sqrt(n));
idx[0]:= 1;
for i:= 1 to n do
begin
k:= appear[a[i]];
j:= 0;
while (j <= lim) and (idx[j] - 1 <> k) do
inc(j);
dec(j);
for j:= j downto 0 do
idx[j + 1]:= idx[j];
f[i]:= i;
for j:= 1 to lim do
begin
if idx[j] = 0 then
break;
f[i]:= min(f[i], f[idx[j] – 1] + sqr(j));
end;
inc(idx[0]);
appear[a[i]]:= i;
end;
writeln(f[n]);
close(input);
close(output);
end.

浙公网安备 33010602011771号