jzoj1299
有N(1<=N<=40000)个奶牛到FJ的餐厅吃饭,餐厅里有M(1<=M<=N)种菜,每头牛有自己喜欢的菜的编号P_i(1<=P_i<=M),每头牛只吃自己喜欢的这道菜。
牛儿们在外面排着队进来,按照排队顺序一批一批进来,每批可以同时进来任意头牛,每一批吃完(注意包括最后一批)都要进行打扫,如果这批牛中一共需要K种菜,那么吃完后的打扫时间为K*K。
请你帮助FJ如何安排各批次使得总打扫时间最少。
给你一个序列,要求用任意个区间覆盖它,定义区间的值为该区间中 不同数字个数 2
求最小区间和
考虑使用DP解决
设f[i]为1~i打扫总时间
用kind(x,y)表示x到y的种类个数
可得f[i]=f[i−j]+kind(i−j,i)2
暴力计算 kind(x,y)
在上文基础上,
用kind(x,y)更新kind(x−1,y)
并且加入剪枝
枚举该批次长度j时
若j2>f[i],那么更大的j也更新不了f[i]了
但是还是会TLE
那么我们考虑空间换时间思想
典型的,我们尝试前缀和优化
我们把程序上下左右看了一遍,和前缀和有个Egg关系啊!
不过,多番思(Read)虑(TJ)后,终于有了思路
我们定义 p[i,k]为食用k种菜,区间右端点为i,的最小左端点
于是就有 fi:=min(fpi,k−1+k2)[0<k<n√]
于是,我们考虑转移 pi,k
当读入x后
[lastx<pj]pi,j:=pi−1,j−1;
[lastx>pj]pi,j:=pi−1,j;
lastx定义为x上一次出现序列位置
const
maxn=40000;
maxm=40000;
var
n,m:longint;
i,j,l,k:longint;
f:array[0..maxn] of longint;
p:array[0..maxn] of longint;
bz:array[0..maxm] of boolean;
function min(a,b:longint):longint;
begin
if a<b then exit(a) else exit(b);
end;
begin
assign(input,'cleanup.in');reset(input);assign(output,'cleanup.out');rewrite(output);
readln(n,m);
for i:=1 to n do
begin
readln(p[i]);
f[i]:=i;
end;
for i:=2 to n do
begin
k:=0;
for j:=0 to i-1 do
begin
f[i]:=min(f[i],f[i-j]+k*k);
if not bz[p[i-j]] then
begin
inc(k);
bz[p[i-j]]:=true;
end;
if k*k>f[i] then break;
end;
for l:=j downto 0 do bz[p[i-l]]:=false;
end;
writeln(f[n]);
close(input);close(output);
end.
const
maxn=40000;
maxm=40000;
var
n,m:longint;
maxlen:longint;
i,j,l,k:longint;
p,f:array[-1..maxn] of longint;
last:array[0..maxm] of longint;
function min(a,b:longint):longint;
begin
if(a<b)then exit(a) else exit(b);
end;
procedure init;
var
i:longint;
begin
readln(n,m);
maxlen:=trunc(sqrt(n))+1;
end;
procedure work;
var
x:longint;
i,j:longint;
begin
f[-1]:=100000000;
readln(x);
last[x]:=1;
f[1]:=1;p[1]:=1;
fillchar(last,sizeof(last),255);
for i:=2 to n do
begin
readln(x);
p[0]:=i;
for j:=maxlen downto 1 do
if last[x]<p[j] then p[j]:=p[j-1];
f[i]:=i;
for j:=1 to maxlen do
f[i]:=min(f[i],f[p[j]-1]+j*j);
last[x]:=i;
end;
end;
procedure print;
begin
writeln(f[n]);
end;
begin
assign(input,'cleanup.in');reset(input);assign(output,'cleanup.out');rewrite(output);
init;
work;
print;
close(input);close(output);
end.