码迷,mamicode.com
首页 > 其他好文 > 详细

USACO泛做

时间:2016-10-01 00:04:16      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:

打扫卫生

题意:一段序列,分为若干段,每段分值为该段中不同数字个数平方,求划分方案使分值和最小。

分析: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.
View Code

 

USACO泛做

标签:

原文地址:http://www.cnblogs.com/qtyytq/p/5925151.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!