題目描述
你有一支由 n 名預備役士兵組成的部隊,士兵從 1 到 n 編號,要將他們拆分 成若干特別行動隊調入戰場。出於默契的考慮,同一支特別行動隊中隊員的編號 應該連續,即為形如的序列。 編號為 i 的士兵的初始戰鬥力為 xi ,一支特別行動隊的初始戰鬥力 x 為隊內 士兵初始戰鬥力之和,即 。
通過長期的觀察,你總結出一支特別行動隊的初始戰鬥力 x 將按如下經驗公 式修正為 ,其中 a, b, c 是已知的係數(a < 0)。 作為部隊統帥,現在你要為這支部隊進行編隊,使得所有特別行動隊修正後 戰鬥力之和最大。試求出這個最大和。
例如,你有 4 名士兵, 。經驗公式中的引數為 a = –1, b = 10, c = –20。此時,最佳方案是將士兵組成 3 個特別行動隊:第一隊包含士兵 1 和士兵 2,第二隊包含士兵 3,第三隊包含士兵 4。特別行動隊的初始戰鬥力分 別為 4, 3, 4,修正後的戰鬥力分別為 4, 1, 4。修正後的戰鬥力和為 9,沒有其它 方案能使修正後的戰鬥力和更大。
輸入輸出格式
輸入格式:
輸入由三行組成。第一行包含乙個整數 n,表示士兵的總數。第二行包含三 個整數 a, b, c,經驗公式中各項的係數。第三行包含 n 個用空格分隔的整數 ,分別表示編號為 1, 2, …, n 的士兵的初始戰鬥力。
輸出格式:
輸出乙個整數,表示所有特別行動隊修正後戰鬥力之和的最大值。
輸入輸出樣例
輸入樣例#1:
4 -1 10 -20
2 2 3 4
輸出樣例#1:
9 說明
20%的資料中,n ≤ 1000;
50%的資料中,n ≤ 10,000;
100%的資料中,1 ≤ n ≤ 1,000,000,–5 ≤ a ≤ –1,|b| ≤ 10,000,000,|c| ≤ 10,000,000,1 ≤ xi ≤ 100
保證2*a*s[i]>t(j1,j2)>t(j2,j3)>……….>t(jn-1,jn)
即維護單調遞減的佇列
隊首取最大值
program df;
var i,j,n,m:longint;
x,y,z,k,t,l,r:int64;
a,b,c,d,s,q,f:array[0..1000000] of int64;
function check(x,y:int64):real;
var i,j:int64;
begin
j:=f[y-1]+d[y]-f[x-1]-d[x];
i:=s[y-1]-s[x-1];
exit(j/i);
end;
begin
readln(n);
readln(x,y,z);
for i:=1 to n do
begin
read(a[i]);
s[i]:=s[i-1]+a[i];
end;
for i:=1 to n do
begin
d[i]:=x*s[i-1]*s[i-1]-y*s[i-1];
c[i]:=x*s[i]*s[i]+y*s[i]+z;
end;
l:=1; r:=0;
for i:=1 to n do
begin
while (r>l) and (check(q[r],i)>check(q[r-1],q[r])) do dec(r);
inc(r);
q[r]:=i;
while (r>l) and (check(q[l],q[l+1])>=2*x*s[i]) do inc(l);
t:=s[i]-s[q[l]-1];
f[i]:=f[q[l]-1]+x*t*t+y*t+z;
end;
writeln(f[n]);
end.
P3628 APIO2010 特別行動隊
轉移方程 f i max f j a s i s j 2 b s i s j c 寫成可以斜率優化的式子 f j a s j 2 b s j c 2 a s i s j f i a s j 2 b s i 然後求 f i 最大值,於是維護上凸包 橫座標單調增,斜率單調減,所以直接上單調佇列即可。in...
P3628 APIO2010 特別行動隊
令 f i 表示前 i 個士兵組成特別行動隊的最大修正戰鬥力之和。對 x 做一遍字首和。轉移方程 f i max x i 兩個負的負負得正不用變號。因為 x i 隨著 i 的增大單調遞增,所以對 2a times x,f a times x 2 b times x 維護下凸包。code includ...
P3628 APIO2010 特別行動隊
你有一支由 n 名預備役士兵組成的部隊,士兵從 1 到 n 編號,要將他們拆分 成若干特別行動隊調入戰場。出於默契的考慮,同一支特別行動隊中隊員的編號 應該連續,即為形如 i,i 1,i k 的序列。編號為 i 的士兵的初始戰鬥力為 xi 一支特別行動隊的初始戰鬥力 x 為隊內 士兵初始戰鬥力之和,...