bzoj 1010 (单调决策优化)

可以很好的证明单调决策性质。用   记sum[i]=sigma(C[1],C[2].....C[k]);f[i]=sum[i]+i;  c=l-1;

有转移dp[i]=min( dp[j]+(f[i]-f[jk]-c)^2);  假死 有2个决策j<k, 对于i点,k决策更优秀 于是可以得到

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <string>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int inf  = 0x3fffffff;
const int mmax = 500010;
LL C[mmax];
LL dp[mmax];
LL sum[mmax];
int n;
LL L;
struct node
{
    int l,r;
    int d;
    node() {}
    node(int l,int r,int d):l(l),r(r),d(d) {}
    void print()
    {
        printf("%d %d %d\n",l,r,d);
    }
}Q[mmax];
LL sqr(LL x)
{
    return x*x;
}
void up(int i,int j)
{
    dp[i]=dp[j]+sqr(sum[i]-sum[j]+i-j-1-L);
}
bool ok(int i,int j,int d)
{
    return dp[d]+sqr(sum[i]-sum[d]+i-d-1-L)>=dp[j]+sqr(sum[i]-sum[j]+i-j-1-L);
}
int find(int l,int r,int j,int d)
{
    int mid;
    r++;
    while(l<r)
    {
        mid=(l+r)>>1;
        if(ok(mid,j,d))
            r=mid;
        else
            l=mid+1;
    }
    return r;
}
void make()
{
    int head=0,tail=0;
    dp[0]=0;
    Q[tail++]=node(0,n,0);
    for(int i=1;i<=n;i++)
    {
        while(Q[head].r<i)
            head++;
        if(Q[head].l<i)
            Q[head].l=i;
        up(i,Q[head].d);
        int tmp=0;
        while(head<tail)
        {
            if(ok(Q[tail-1].l,i,Q[tail-1].d))
            {
                tmp=Q[tail-1].l;
                tail--;
            }
            else
            {
                tmp=find(Q[tail-1].l,Q[tail-1].r,i,Q[tail-1].d);
                Q[tail-1].r=tmp-1;
                break;
            }
        }
        if(tmp<=n)
            Q[tail++]=node(tmp,n,i);
    }
}
int main()
{

    while(cin>>n>>L)
    {
        sum[0]=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&C[i]);
            sum[i]=sum[i-1]+C[i];
        }
        make();
        printf("%lld\n",dp[n]);
    }
    return 0;
}

dp[k]+(f[i]-f[k]-c)^2<dp[j]+(f[i]-f[j]-c)^2;

对于一个x>i  假设f[x]=f[i]+v;对于决策j,k,若决策k优于决策j  ,必然

dp[k]+(f[x]-f[k]-c)^2<dp[j]+(f[x]-f[j]-c)^2;

于是dp[k]+(f[i]+v-f[k]-c)^2<dp[j]+(f[i]-v-f[j]-c)^2;

只要2v(f[i]-f[k]-c)+v^2<2v(f[i]-f[j]-c)

优于v>0   f[k]>f[j]  这是必然成立的  ,所以可以很好的证明单调决策性质,然后可以根据《1D/1D动态规划初步》论文的写法做。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-28 00:59:24

bzoj 1010 (单调决策优化)的相关文章

BZOJ 1010 dp 斜率优化

题意: 给一段数列,要求分成若干段,有一个公式可算每段的花费,求整段数列最小花费. 题意很裸,不难得出状态转移方程:dp[i]=min{dp[j]+(sum[i]-sum[j-1]+i-j-l)^2}(j<i); 但是数据范围很大,o(n^2)过不了,于是就用斜率优化变成n的,就过了. 下面详细讲一下斜率优化: 斜率优化就是维护一个凸壳,使其严格上凸或下凸,具体情况具体分析,就本题而言设有k<j<i,且i从k转移来的, 则:dp[k]+(sum[i]-sum[k-1]+i-k-l)^2&

BZOJ - 1010【斜率优化DP】

1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 9961  Solved: 4056[Submit][Status][Discuss] Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压 缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过 压缩后变成一维长度为Ci.为了方便整理

BZOJ 1010 玩具装箱toy(四边形不等式优化DP)(HNOI 2008)

Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的.同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第i件玩具到第j个玩具放到一个容器中,那么容器的长度将为 x=j-i+Sigma(Ck) i<

BZOJ 1855 股票交易(单调队列优化DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1855 题意:最近lxhgww又迷上了投资股票, 通过一段时间的观察和学习,他总结出了股票行情的一些规律. 通过一段时间的观察,lxhgww预测到了未来T天内某只股票的走势,第i天的股票买入价为每股APi,第i天的股票卖出价为每股BPi(数据保证对于每 个i,都有APi>=BPi),但是每天不能无限制地交易,于是股票交易所规定第i天的一次买入至多只能购买ASi股,一次卖出至多只能卖出BS

斜率优化专题2——bzoj 1010 [HNOI2008]玩具装箱toy 题解

[原题] 1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 5434  Solved: 1969 [Submit][Status] Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具经过压缩后变成一维长度为Ci.为了方便整理,P教授

BZOJ 2806 [Ctsc2012]Cheat ——后缀自动机 单调队列优化DP

先建出广义后缀自动机. 然后跑出文章中每一个位置的最大匹配距离. 然后定义$f[i]$表示匹配到以$i$结尾的串时,最长的匹配距离. 显然可以二分$L$的取值. 然后容易得到$DP$方程 $f[i]=max(f[i-1],f[j]+i-j)(j<=i-L)$ 然后就发现$j$属于一个区间,然后就可以单调队列优化了. #include <map> #include <ctime> #include <cmath> #include <queue> #in

BZOJ 1855 [Scoi2010]股票交易 单调队列优化DP

题意:链接 方法:单调队列优化DP 解析:噢又是一道情况很多的题,然而三种更新我又落下一种导致样例不过,后来看题解才恍然- -最SB的一种更新居然忘了. 状态好想f[i][j]代表前i天有j双袜子时的最大利润. 三种更新: 第一种:f[i][j]=max(f[i][j],f[i?1][j]):(然而我忘了这一种) 第二种:买入f[i][j]=max(f[i][j],f[i?w?1][k]?(j?k)?a[i].ap)(k>=j?a[i].as); 第三种:卖出f[i][j]=max(f[i][j

HDU 3401 Trade dp 单调队列优化

戳这里:3401 题意:给出第 i 天的股票买卖价格(APi,BPi),以及每天股票买卖的数量上限(ASi,BSi),要求任两次交易需要间隔 W 天以上,即第 i 天交易,第 i + W + 1 天才能再交易,求最多能赚多少钱 思路:dp[i][j] = max(dp[i - 1][j], max(dp[f][k] - (j - k) * APi[i]), max(dp[f][k] + (k - j) * BPi[i])); 从式子中观察出,若两天都持有股票数 j 时,之后的那一天所赚的钱不小于

bzoj 1047 单调队列

做4次单调队列优化DP. 1 /************************************************************** 2 Problem: 1047 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:2088 ms 7 Memory:16756 kb 8 ****************************************************************/ 9 10