apio2010 特別行動隊 斜率優化的dp

2021-06-10 05:06:21 字數 1606 閱讀 4835

[題目簡述]

給你乙個序列,你要將他們分成連續的若干份.每乙份帶給你的收益是ax^2+bx+c,其中x是這乙份的和,a<0

[題解]

對於這道題,我們可以很容易的寫出方程:f[i]=max(f[j]+a*(s[i]-s[j])^2+b*(s[i]-s[j])+c);因為資料範圍是100w,所以我們猜測這個dp要用斜率優化或單調佇列優化.

現在我們對他做一下變形.

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

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

可以發現,f[j]+a*a[j]*a[j]-b*s[j]只與j有關,a*s[i]*s[i]+b*s[i]+c只與i有關,2*a*s[i]*s[j]與i,j有關且單調遞減(a<0),而f[j]+a*a[j]*a[j]-b*s[j]則沒有單調性.

我們令k=a*s[i]*s[i]+b*s[i]+c,x[i]=2*a*s[i],y[i]=f[i]+a*a[i]*a[i]-b*s[i],則:f[i]=max(y[i]+s[i]*x[i])+k

令p=y[j]+s[i]*x[j],我們的目標就是最大化p.移項得:y[j]=p-s[i]*x[j].

我們再令x[j]=-x[j],則:y[j]=s[i]*x[j]+p.其中,x隨j單調遞增.由於s隨i單調遞增,所以直線的斜率也單調遞增,所以我們可以利用斜率優化來解決這道題.

code:

program commando;

type int=longint;real=extended;

var i,j,m,l,r,n:int;

a,b,k,c:real;

x,y,f,s:array[0..1000000]of real;

q:array[0..1000000]of int;

begin

assign(input,'commando.in');reset(input);

assign(output,'commando.out');rewrite(output);

read(n);

read(a,b,c);s[0]:=0;

for i:=1 to n do begin

read(s[i]);s[i]:=s[i-1]+s[i];

end;

l:=1;r:=1;q[l]:=0;f[0]:=0;

for i:=1 to n do begin

k:=c+b*s[i]+a*s[i]*s[i];

while(l(y[q[r]]-y[i])/(x[q[r]]-x[i]))do dec(r);

inc(r);q[r]:=i;

end;

write(f[n]:0:0);

close(input);close(output);

end.

另外,我想申明一下,由於本人寫blog的主要目的是將剛學過的東西鞏固一下,所以**的效率不一定有多高,實現方式不一定很精簡,請某些同學就不要挑一些小毛病了.貼上來的程式只是做乙個參考,不過我還是會保證正確性的.

by qw

apio2010特別行動隊(斜率優化)

這題是上凸形,題目當中,還是要注意括號的問題。因為括號套錯了一層re了好幾次 關於,斜率優化,感覺一般的常數項,和i有關的就都放在右邊吧,比如已知的那些常量,由此盡量保證左邊的上下分子分母都是正的應該是好處理吧 感覺 斜率優化,推出的方程,是大於號,那麼上凸,維護斜率遞減。小於號,下凸,維護斜率遞增...

APIO2010 特別行動隊

你有一支由 n 名預備役士兵組成的部隊,士兵從 1 到 n 編號,要將他們拆分 成若干特別行動隊調入戰場。出於默契的考慮,同一支特別行動隊中隊員的編號 應該連續,即為形如 i,i 1,i k i,i 1,i k 的序列。編號為 i 的士兵的初始戰鬥力為 xi 一支特別行動隊的初始戰鬥力 x 為隊內 ...

APIO2010 特別行動隊

dp方程 dp i max dp i dp j a sum i sum j 2 b sum i sum j c 暴力還是可以過一些點的 不止20pts 甚至有人說他暴力水過去了。我們現在考慮正解,正解還是斜率優化。維護乙個上凸包qwqwq 設 dp i 表示到士兵i所能達到的最大戰力,sum i 表...