(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
题目:传送门
题目描述及样例在最下面。
思路:
学一学决策单调性,斜率优化。
s u m [ i ] = ∑ a r [ i ] + i sum[i] = \sum ar[i] + i sum[i]=∑ar[i]+i
f [ i f[i f[i]为装 1 1 1到 i i i的玩具所需花费的钱。
f [ i ] = m i n ( f [ j − 1 ] + ( s u m [ i ] − s u m [ j − 1 ] − c ) 2 ) , c = L + 1 f[i]=min(f[j-1]+(sum[i]-sum[j-1]-c)^2), c = L + 1 f[i]=min(f[j−1]+(sum[i]−sum[j−1]−c)2),c=L+1
第一步:
若有 j < k < i j < k < i j<k<i,如果点 i i i 选择从点 k k k 转移的决策优于(不劣于)从点 j j j 转移的决策,即
f [ k ] + ( a r [ i ] − a r [ k ] − c ) 2 ≤ f [ j ] + ( a r [ i ] − a r [ j ] − c ) 2 f[k] + (ar[i]-ar[k]-c)^2 \leq f[j] + (ar[i]-ar[j]-c)^2 f[k]+(ar[i]−ar[k]−c)2≤f[j]+(ar[i]−ar[j]−c)2
= > f [ k ] − 2 ∗ a r [ i ] ∗ ( a r [ k ] + c ) + ( a r [ k ] + c ) 2 ≤ f [ j ] − 2 ∗ a r [ i ] ∗ ( a r [ j ] + c ) + ( a r [ j ] + c ) 2 => f[k] - 2*ar[i]* (ar[k]+c) + (ar[k]+c)^2 \leq f[j] - 2*ar[i]* (ar[j]+c) + (ar[j]+c)^2 =>f[k]−2∗ar[i]∗(ar[k]+c)+(ar[k]+c)2≤f[j]−2∗ar[i]∗(ar[j]+c)+(ar[j]+c)2
= > f [ k ] − f [ j ] + ( a r [ k ] + c ) 2 − ( a r [ j ] + c ) 2 ≤ 2 ∗ a r [ i ] ∗ ( a r [ k ] − a r [ j ] ) => f[k] - f[j] + (ar[k]+c)^2 - (ar[j]+c)^2 \leq 2*ar[i]* (ar[k]-ar[j]) =>f[k]−f[j]+(ar[k]+c)2−(ar[j]+c)2≤2∗ar[i]∗(ar[k]−ar[j])
= > ( f [ k ] − f [ j ] + ( a r [ k ] + c ) 2 − ( a r [ j ] + c ) 2 ) 2 ∗ ( a r [ k ] − a r [ j ] ) ≤ a r [ i ] => \frac {(f[k] - f[j] + (ar[k]+c)^2 - (ar[j]+c)^2)}{2* (ar[k]-ar[j])} \leq ar[i] =>2∗(ar[k]−ar[j])(f[k]−f[j]+(ar[k]+c)2−(ar[j]+c)2)≤ar[i]
将上述式子定义为
j
j
j和
k
k
k的斜率。注意:
j
<
k
j \lt k
j<k。
如果当前情况在点
k
k
k 处决策优于在点
j
j
j 处决策,则有:
斜
率
(
j
,
k
)
≤
a
r
[
i
]
斜率(j, k) \le ar[i]
斜率(j,k)≤ar[i]
( f [ k ] − f [ j ] + ( a r [ k ] + c ) 2 − ( a r [ j ] + c ) 2 ) 2 ∗ ( a r [ k ] − a r [ j ] ) ≤ a r [ i ] \frac {(f[k] - f[j] + (ar[k]+c)^2 - (ar[j]+c)^2)}{2* (ar[k]-ar[j])} \leq ar[i] 2∗(ar[k]−ar[j])(f[k]−f[j]+(ar[k]+c)2−(ar[j]+c)2)≤ar[i]
第二步:
使用单调队列来维护这一关系。使得队列中的斜率单调上升。
head为队首,tail为队尾。新加入的点为i。
斜率(head,head+1) <= ar[i],则将head点pop出去。
因为head+1点除的决策优于head点。
如果斜率(tail, i) < 斜率(tail-1,tail),则将tail点pop出去。
如果不pop出去,无法维持队列中元素的决策单调性(单调上升)。
AC代码:
/*
f[k] + (ar[i]-ar[k]-c)^2 <= f[j] + (ar[i]-ar[j]-c)^2
=> f[k] - 2*ar[i]*(ar[k]+c) + (ar[k]+c)^2 <= f[j] - 2*ar[i]*(ar[j]+c) + (ar[j]+c)^2
=> f[k] - f[j] + (ar[k]+c)^2 - (ar[j]+c)^2 <= 2*ar[i]*(ar[k]-ar[j])
=> (f[k] - f[j] + (ar[k]+c)^2 - (ar[j]+c)^2)/2*(ar[k]-ar[j]) <= ar[i]
*/
#define o2(x) (x)*(x)
const int MXN = 1e5 + 7;
int n, m;
LL ar[MXN], sum[MXN], dp[MXN];
int que[MXN], head, tail;
LL K(int j, int k) {
return (dp[k] - dp[j] + o2(sum[k]+m) - o2(sum[j]+m));
}
int main() {
#ifndef ONLINE_JUDGE
freopen("/home/cwolf9/CLionProjects/ccc/in.txt", "r", stdin);
//freopen("/home/cwolf9/CLionProjects/ccc/out.txt", "w", stdout);
#endif
n = read(), m = 1 + read();
for(int i = 1; i <= n; ++i) ar[i] = read(), sum[i] = sum[i-1] + ar[i];
for(int i = 1; i <= n; ++i) sum[i] += i;
//head = tail = 0, que[0] = 0;表示前面全选的策略
for(int i = 1; i <= n; ++i) {
while(head < tail && K(que[head], que[head + 1]) <= 2 * sum[i] * (sum[que[head+1]]-sum[que[head]])) ++ head;
if(head > tail) dp[i] = o2(i - 1 + sum[i] - i - m + 1);
else dp[i] = dp[que[head]] + o2(sum[i] - sum[que[head]] - m);
while(head < tail && K(que[tail], i)*(sum[que[tail]] - sum[que[tail-1]])
<= K(que[tail-1], que[tail])*(sum[i]-sum[que[tail]])) -- tail;
que[++tail] = i;
// debug(que[head], que[head+1])
}
printf("%lld\n", dp[n]);
#ifndef ONLINE_JUDGE
cout << "time cost:" << clock() << "ms" << endl;
#endif
return 0;
}
BZOJ1010: Description
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压
缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为1…N的N件玩具,第i件玩具经过
压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容
器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一
个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<=K<=j 制作容器的费用与容器的长度有关,根据教授研究,
如果容器长度为x,其制作费用为(X-L)^2.其中L是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容
器,甚至超过L。但他希望费用最小.
Input
第一行输入两个整数N,L.接下来N行输入Ci.1<=N<=50000,1<=L,Ci<=10^7
Output
输出最小费用
Sample Input
5 4
3 4 2 1 4
Sample Output
1