poj 3017 cut the sequence
分析:不好理解,大体上知道了优化的方向,但是需要单调队列和平衡树(或堆)来维护。
比较难以理解。
f[i]=min{f[k]+max{a[k+1],.....,a[i]}}.
n2的枚举没有问题,优化势在必行。
我们另A[I,J]表示i到j的最大值,那么如果A[i+1,j]=A[i+2,j],那么f[i]+A[i+1,j]<f[i+1]+A[i+2,j],
所以很显然f[i]=min{f[k]+A[k+1,i]}有用的K值都是满足某段区间的最大值。
如果用单调队列维护a[i]使队列中的元素a值单调递减,那么显然可以用于更新的就是a[q[i]]+f[q[i-1]],但是与其他题目不同的是队首元素并不是最优的,所以可以用堆或者平衡树来迅速找到最大值。
核心代码:
procedure ins(c,d:longint);
begin
sum:=sum+c;
while sum>m do
begin
inc(last);
sum:=sum-a[last];
end;
while (v[tail]<=c) and(tail>head) do
begin
delete(z[tail]);
dec(tail);
end;
inc(tail);
v[tail]:=c;
p[tail]:=d;
end;
procedure solve;
var
i: longint;
begin
for i:= 1 to n do
begin
ins(a[i],i);
while p[head+1]<last do
begin
inc(head);
delete(z[head]);
end;
p[head]:=last;
delete(z[head+1]);
insert(f[p[head]]+v[head+1],head+1,z[head+1]);
insert(f[p[tail-1]]+v[tail],tail,z[tail]);
f[i]:=h1[1];
end;
writeln(f[n]);
end;
浙公网安备 33010602011771号