1. 程式人生 > >【筆記篇】斜率優化dp(三) APIO2010特別行動隊

【筆記篇】斜率優化dp(三) APIO2010特別行動隊

tex http span type 2-2 參加 math 就是 裏的

旁聽了一波給舒老師和學弟的pkuwc面試講座...
這裏有一段隱身的吐槽, 想看的請自己想辦法觀看. 不想看的跳過這一段看似空白的東西就好了...

剛開始ATP學姐給我們講了自己面試的時候的事情..描繪了一下當時面試的場面和當時問的問題..(ATP學姐太可愛了OvO)可能準備的也不是很充足 用了好多的"然後" "就是"之類的, 自己也在吐槽, 老師後來也槽來著, (不過還是超可愛n(≧▽≦)n)旁邊老師在記錄, 尤其記下了一個什麽"你認為學習信息男生和女生有什麽區別?"的問題..(可是這種問題怎麽可能問男生啊講道理), 然後學姐講完之後就是shallwe大爺來講, shallwe大爺還準備了稿子, 然後就講了一些面基技巧.. 但是也是比較老生常談的東西, 之前參加各種各樣的風采大賽回答問題的時候也就是那一套之類的 小時候還能做到, 現在反而越來越不行了.. 然後講了各種各樣的問題, 說是問的問題都在blog裏面.. 老師還說要blog的地址來給學弟學妹什麽的(那也就是包括我們咯), 但是聽完回來一看這blog裏的東西能給老師看?! 各種吐槽甚至還有吐槽面試培訓的.. 然後他們就回去學習了= =

老師就開始種講評, 還讓兩個人分別回答了上面說的男女區別問題 然後兩個都做出了比較"片面"的回答, 老師就說要往什麽三個方面想之類的說了一堆, 反正就是不懟人的同時優雅地裝逼的技巧, (什麽在北大不說清華比北大強之類的, 說了確定不是石樂誌麽= =)然後再就是"你有什麽缺點", 聽說年年問...(大家準備好的答案都能倒著背了好麽)就說要找個"不是缺點的缺點", 然後兩個人都說自己比較執著啊... 就不能找點有創意的麽←←, 感覺全世界都有執著得有點傻這個缺點... 要我的話可能會說自己好奇心過強? 反正就這麽著吧. 然後還有什麽進門關門鞠躬瞅瞅有沒有廢紙倒拖把什麽的... 反正就是一些雞湯文裏描寫的面試的細節問題, 還有著裝問題, 我覺得只要不是明顯違和的穿女裝應該都不是什麽大問題吧←
←(對沒錯哪怕是可愛的男孩紙穿女裝其實也是可以噠~(≧▽≦)/~)兩個人又練了一波關門鞠躬之類的 終於煎熬地熬過去了.. 然後趕緊去了個廁所 畢竟半下午+半晚上沒有去了.. 回來之後就調這個題 不過很快就調A了這還比較和善..(嗯 主要原因是這次的luogu沒有出鍋...)

===我===是===一===條===分===割===線===我===也===是===一===扇===傳===送===門===

繼續吐槽, 不過這次跟題目有關了.. 聽完回來就繼續寫這道題啊...
這道題顯然支持\(O(n)\)的做法, (感覺1e6的話套個log就不是很靠譜了)
那就是要優化, 就是要化式子嘛..然後剛開始以為這個題是

\[\sum_{i=1}^n(ax_i^2+bx_i+c)=a\sum_{i=1}^nx_i^2+bs_n+n*c\]
然後最大化\(\sum_{i=1}^nx_i^2\)之後直接輸出\(a*f[n]+b*s[n]+n*c\)的大水題,
但是發現好像樣例差了好多好多...結果發現自己快讀沒讀負數...
然後改完之後輸出負數了... 手玩了一下發現好像這個\(n*c\)\(n\)好像不一定是題目裏給的\(n\)...
那就不能這麽化式子了, 就開始重新化.. 還是得從狀態轉移方程入手...
\[f[i]=max\{f[j]+a(s[i]-s[j])^2+b(s[i]-s[j])+c\}(j\in[1,i))\]
然後去括號
\[f[i]=f[j]+as[i]^2-2as[i]s[j]+as[j]^2+bs[i]-bs[j]+c\]
移項能得到
\(f[j]+as[j]^2-bs[j]\)=\(2as[i]\)\(s[j]\)+\(f[i]-(as[i]^2+bs[i]+c)\)
由於題目中已經給了\(-5<a<-1\), 所以斜率一定是<0的, 而\(f[j]+as[j]^2-bs[j]\)直觀上很明顯是遞減的. 我們考慮凸性對結果的影響.
技術分享圖片
我們考慮中間的點在位於兩個斜率中間(大於大斜率小於小斜率顯然不優就不考慮了)的情況.
發現如果是位於下凸殼的點是不優的, 而位於上凸殼的點是優的, 我們就要維護一個上凸殼.

而這裏的斜率\(2as[i]\)顯然是遞減的(絕對值遞增), 所以
技術分享圖片
如果一個斜率一旦已經小於(絕對值大)於隊首的邊, 那麽隊首的點在以後也不會優了 我們讓隊首出隊即可.
依然是維護一個單調隊列.
然後就沒有了. 代碼: 1A了哈哈哈哈 (放肆地笑ing...)

#include <cstdio>
const int N=16+6;
typedef long long LL;
LL f[N],s[N]; int q[N],h,t,a,b,c,n;
inline int gn(int a=0,char c=0,int f=1){
    for(;(c<48||c>57)&&c!='-';c=getchar());if(c=='-')f=-1,c=getchar();
    for(;c>='0'&&c<='9';c=getchar()) a=a*10+c-'0'; return a*f;
}
inline double slope(int x,int y){
    return 1.0*(f[x]+a*s[x]*s[x]-b*s[x]-f[y]-a*s[y]*s[y]+b*s[y])/(s[x]-s[y]);
}
int main(){ n=gn(); a=gn(); b=gn(); c=gn();
    for(int i=1;i<=n;++i) s[i]=s[i-1]+gn();
    for(int i=1;i<=n;++i){
        while(h<t&&slope(q[h],q[h+1])>=2*a*s[i]) ++h;
        f[i]=f[q[h]]+a*(s[i]-s[q[h]])*(s[i]-s[q[h]])+b*(s[i]-s[q[h]])+c;
        while(h<t&&slope(q[t],q[t-1])<=slope(q[t],i)) --t;
        q[++t]=i;
    } printf("%lld",f[n]);
}

【筆記篇】斜率優化dp(三) APIO2010特別行動隊