解题报告 QUE

即 usaco Mar 09 Cleaning Up

【转】

 

题意Overview
N头奶牛,每头那牛都有一个标号Pi1 <= Pi <= M <= N <= 40000。 现在Farmer John要把这些奶牛分成若干段,定义每段的不河蟹度为:若这段里有k个不同的数,那不河蟹度为k*k。那总的不河蟹度就是所有段的不河蟹度的总和。

题解Solution
直观就会有一个N^2DP

首先是如果把它们切成N段的话,答案上界是N。所以如果某[i, j]kN−−  ,这肯定不是最优解的一部分,可以break

diff[i, j]表示[i, j]间不同的数的数目。
决策到f[i]时,若k < j, 且有diff[k, i] == diff[j, i],那么直接skipj直接跳到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.

 

原文地址:https://www.cnblogs.com/SueMiller/p/2229111.html