BZOJ-1010-斜率优化-决策单调性

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

题目:传送门

 题目描述及样例在最下面。

思路:

学一学决策单调性,斜率优化。

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[j1]+(sum[i]sum[j1]c)2),c=L+1

第一步:

若有 j &lt; k &lt; i j &lt; k &lt; 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)2f[j]+(ar[i]ar[j]c)2

= &gt; 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 =&gt; 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]2ar[i](ar[k]+c)+(ar[k]+c)2f[j]2ar[i](ar[j]+c)+(ar[j]+c)2

= &gt; f [ k ] − f [ j ] + ( a r [ k ] + c ) 2 − ( a r [ j ] + c ) 2 ≤ 2 ∗ a r [ i ] ∗ ( a r [ k ] − a r [ j ] ) =&gt; 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)22ar[i](ar[k]ar[j])

= &gt; ( f [ k ] − f [ j ] + ( a r [ k ] + c ) 2 − ( a r [ j ] + c ) 2 ) 2 ∗ ( a r [ k ] − a r [ j ] ) ≤ a r [ i ] =&gt; \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 &lt; 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值