APIO2010 特別行動隊

2022-03-03 15:49:52 字數 1314 閱讀 2571

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]\)表示字首和

\(dp[i]=max(dp[i],dp[j]+a*\sum_^x[k]^2+b*\sum_^i+c)\)

\(=max(dp[i],dp[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c)\)

用斜率優化更新的時候——

\(dp[i]=dp[j]+a*sum[i]^2+a*sum[j]^2-2a*sum[i]*sum[j]+b*sum[i]-b*sum[j]+c\)

\(2a*sum[i]*sum[j]+dp[i]-b*sum[i]-a*sum[i]^2=dp[j]+a*sum[j]^2-b*sum[j]+c\)

\(2a*sum[i]*x+b=y\)

**如下:

#include#include#include#include#include#define maxn 1000010

using namespace std;

int n,head=1,tail=1;

long long a,b,c;

long long pre[maxn],sum[maxn],dp[maxn],q[maxn];

inline long long x(int p)

inline long long y(int p)

inline double k(int p,int q)

int main()

{ #ifndef online_judge

freopen("ce.in","r",stdin);

#endif

scanf("%d",&n);

scanf("%lld%lld%lld",&a,&b,&c);

for(int i=1;i<=n;i++) scanf("%lld",&pre[i]),sum[i]=sum[i-1]+pre[i];

for(int i=1;i<=n;i++)

{while(head2*a*sum[i]) head++;

dp[i]=y(q[head])-2*a*sum[i]*x(q[head])+b*sum[i]+a*sum[i]*sum[i];

while(head其實單調佇列也就只維護兩點,head維護的是「第一條斜率大於來切的斜線」,tail維護的是凸包形態qwq

APIO2010 特別行動隊

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

APIO2010 特別行動隊

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

APIO 2010 特別行動隊

題目鏈結 演算法 設前i個士兵 修正 後的最大戰鬥力為fi 令sumi表示x的字首和 顯然 有狀態轉移方程 fi max 對該式進行化簡 得 fi max 令yj fj asumj 2 xj sumj 則 fi max 那麼yj xj 2asumi b fi asumi 2 bsumi c 顯然我們...