APIO2010 特别行动队

题目不在累述,在RQNOJ或八中上都有。

朴素方程很好写

f[i]=max{f[j]+a*sqr(s[i]-s[j])+b*(s[i]-s[j])+c}

典型的1D/1D方程,有数据范围来看,一定有O(n)算法,于是模式基本就确定下来了,我们要对方程进行变形。

设对于f[i]决策x优于y且x<y

则:f[x]+a*(s[i]-s[x])*(s[i]-s[x])+b*(s[i]-s[x])+c>f[y]+a*(s[i]-s[y])*(s[i]-s[y])+b*(s[i]-s[y])+c

→f[x]+a*s[i]*s[i]-2*a*s[i]*s[x]+a*s[x]*s[x]+b*s[i]-b*s[x]+c>f[y]+a*s[i]*s[i]-2*a*s[i]*s[y]+a*s[y]*s[y]+b*s[i]-b*s[y]+c

→f[x]-2*a*s[i]*s[x]+a*s[x]*s[x]-b*s[x]>f[y]-2*a*s[i]*s[y]+a*s[y]*s[y]-b*s[y]

我们令g[i]=f[i]+a*s[i]*s[i]-b*s[i]

则有g[x]-2*a*s[i]*s[x]>g[y]-2*a*s[i]*s[y]

→g[x]-g[y]>2*a*s[i]*(s[x]-s[y])

由于x<y且每一个战斗力均为正,所以s[x]-s[y]<0

所以(g[x]-g[y])/(s[x]-s[y])<2*a*s[i]

左边的式子是什么?两点连线的斜率啊!由以上式子,我们可以得到

对于当前状态i,如果最优状态为p,那么对于j1<p 有 k(j1,p)>=2*a*s[i]

                  对于p<j2 有 k(p,j2)<2*a*s[i]

满足单调型!!!!!!

相当与维护一个平面上的点集(s[i],g[i])凸包,每次决策也一定单调,这就让我们用一个队列来维护这个凸包,每个决策最多入队出队各一次,平摊时间复杂度为O(n)

问题完美解决,特别的队列中有一个点时,它就是当前决策最优点。

View Code
 1 program APIO(input,output);
 2 var
 3     f,g     :array[0..1000050] of int64;
 4     s     :array[0..1000050] of longint;
 5     q     :array[0..1000050] of longint;
 6     a,b,c    :longint;
 7     n     :longint;
 8 procedure init;
 9 var
10     i:longint;
11 begin
12     readln(n);
13     readln(a,b,c);
14     s[0]:=0;
15     for i:=1 to n do
16     begin
17         read(s[i]);
18         s[i]:=s[i]+s[i-1];
19     end;
20 end;{ init }
21 function K(x,y:longint):double; 
22 begin
23     exit(double(g[y]-g[x])/double(s[y]-s[x]));
24 end; { K }
25 procedure main;
26 var
27     i        :longint;
28     head,tail:longint;
29     bestK     :double;
30 begin
31     f[0]:=0;
32     head:=1;
33     tail:=1;
34     q[1]:=0;
35     for i:=1 to n do
36     begin
37         bestK:=double(2*a*s[i]);
38         while (tail-head+1>1)and(K(q[head],q[head+1])>=bestK) do
39             inc(head);
40         f[i]:=int64(f[q[head]])+int64(a)*int64(s[i]-s[q[head]])*int64(s[i]-s[q[head]])+int64(b)*int64(s[i]-s[q[head]])+int64(c);
41         g[i]:=int64(f[i])+int64(a)*int64(s[i])*int64(s[i])-int64(b)*int64(s[i]);
42         while (tail-head+1>=2)and(K(q[tail],i)>K(q[tail-1],q[tail])) do
43             dec(tail);
44         inc(tail);
45         q[tail]:=i;
46     end;
47 end;
48 procedure print;
49 begin
50     writeln(f[n]);
51 end;
52 begin
53     init;
54     main;
55     print;
56 end.
posted @ 2012-04-19 08:36  Codinginging  阅读(736)  评论(0编辑  收藏  举报