题意:

  有n个玩具,要将它们分为若干组,玩具长度C可能不同。给出n个玩具的摆放顺序,连续的任意多个玩具都可以成为一组。区间[i,j]成为一组的费用是cost=(j-i+Sigma(Ck)-L)2且i<=k<=j。给定n和L和每个玩具的长度,问分组后费用总和是多少? (n<=5*104)。

思路:

  转移方程:dp[i]=min( dp[j]+(sum[i]-sum[j]+i-j+1-L)2  )。sum[i]表示前i件玩具长度的总和,0<j<i,(i-j+1)表示与i同组的玩具个数。

  根据方程是可以推出这题是满足决策单调性的。以下是抄来的证明,稍微修改:

  令f[i]=sum[i]+i, c=1+L,则dp[i]=min( dp[j]+(f[i]-f[j]-c)2  )

  1.证明决策单调性

  假设在状态i处的k决策优于j决策,且j<k,那么 dp[k]+(f[i]-f[k]-c)2<=dp[j]+(f[i]-dp[j]-c)2

  而对于i后面的某个状态t,设f[t]=f[i]+v,先不管v是多少。

  要证明:dp[k]+(f[t]-f[k]-c)2<=dp[j]+(f[t]-f[j]-c)2

  只要证(将f[t]=f[i]+v代入):dp[k]+(f[i]+v-f[k]-c)2<=dp[j]+(f[i]+v-f[j]-c)2

  只要证dp[k]+(f[i]-f[k]-c)2+2v*(f[i]-f[k]-c)+v2  <=  dp[j]+(f[i]-f[j]-c)2+2v*(f[i]-f[j]-c)+v2

  由于假设,所以只要证: 2v*(f[i]-f[k]-c)<=2v*(f[i]-f[j]-c)。

  即证:f[k]>=f[j](显然)

  证明完毕

  思路很明确,一直卡在二分上面,噗。

  用一个队列来维护这些区间段,由于区间段必定是连在一起的,所以只需要记录左端点L以及更新这个区间的决策k。如果队列为空,则后面全部由i来更新得到,若非空,那么判断队尾的L,是否由i来更新会更优,若是,则pop掉队尾,继续同样的动作,直到队列为空或者i作为决策不如队尾的L更好,那么i可以更新的就是[L,n]之中的尾部区间[r,n],而r可以用二分查找的方式。细节上很容易写挫,比如i决策可能完全都可以用武之地,不用二分去找了,否则会错;二分时必定要保证r由i来更新更佳,且有可能会出现等于的情况。复杂度O(nlogn),斜率优化等再写。

 //#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <set>
#include <deque>
#include <map>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define back que[rear-1]
#define INF 0x7f7f7f7f
#define LL long long
#define ULL unsigned long long
using namespace std;
const double PI = acos(-1.0);
const int N=; LL len[N], dp[N], L;
int q[N], d[N], n, l, r; //区间以及决策
LL cost(int j,int i) //用j来更新i的费用
{
return dp[j]+(len[i]-len[j]-L)*(len[i]-len[j]-L);
} int find(int i,int k,int st)
{
int ll=st, rr=n;
while(ll<rr)
{
int mid=rr-(rr-ll+)/;
if( cost(i,mid)<cost(k,mid)) rr=mid;
else ll=mid+;
}
return rr;
}
LL cal()
{
l=r=;
d[]=;q[]=; //初始时,0可以更新[1,n]
for(int i=; i<=n; i++)
{
dp[i]=cost(d[l], q[l]++); //q[l]永远等于i
if( l<r && q[l]==q[l+] ) l++; while( l<=r && cost(i,q[r])<cost(d[r],q[r]) ) r--;
if(l>r) //只能用i来更新
{
q[++r]=i+;
d[r]=i;
}
else if( cost(i,n)<cost(d[r],n))
{
int tmp=find(i, d[r], q[r]);
q[++r]=tmp;
d[r]=i;
}
}
return dp[n];
} int main()
{
//freopen("input.txt","r",stdin);
while(~scanf("%d%lld",&n,&L))
{
L++;len[]=;
for(int i=; i<=n; i++)
{
scanf("%lld",&len[i]);
len[i]+=len[i-];
}
for(int i=; i<=n; i++) len[i]+=i;
printf("%lld\n", cal() );
}
return ;
}

AC代码

HYSBZ 1010 玩具装箱toy (决策单调DP)的更多相关文章

  1. BZOJ 1010: 玩具装箱toy (斜率优化dp)

    Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...

  2. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

  3. 『玩具装箱TOY 斜率优化DP』

    玩具装箱TOY(HNOI2008) Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊 ...

  4. bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp

    1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 11893  Solved: 5061[Submit][S ...

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

    Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...

  6. BZOJ 1010 玩具装箱toy(斜率优化DP)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1010 题目大意:P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他 ...

  7. 洛谷P3195 [HNOI2008]玩具装箱TOY(单调队列优化DP)

    题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具, ...

  8. bzoj 1010 玩具装箱toy -斜率优化

    P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1...N的N件玩具,第i件玩具 ...

  9. P3195 [HNOI2008]玩具装箱TOY 斜率优化dp

    传送门:https://www.luogu.org/problem/P3195 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任 ...

随机推荐

  1. a possible low-level optimization

    http://www.1point3acres.com/bbs/thread-212960-1-1.html 位的vector<int> counts,遍历nums,然后counts[nu ...

  2. 利用CSS3给图片添加旋转背景特效

    首先看旋转特效:http://***/demo/201512/2015-12-09-css3-image-hover-animate/index.html 这是一款纯CSS3实现的当鼠标滑过图片时文字 ...

  3. HDU - 4704 sum 大数取余+欧拉降幂

    Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submi ...

  4. Android开发中,那些让你觉得相见恨晚的方法、类或接口

    Throwable类中的getStackTrace()方法,根据这个方法可以得到函数的逐层调用地址,其返回值为StackTraceElement[],而在StackTraceElement类中有四个方 ...

  5. 函数PARSENAME使用和截取字符串

    MS SQL server有一个函数PARSENAME ( 'object_name' , object_piece ). 函数有2个参数: Object_name 检索的对象名称.即是:服务器名.数 ...

  6. Keras输出每一层网络大小

    示例代码: model = Model(inputs=self.inpt, outputs=self.net) model.compile(loss='categorical_crossentropy ...

  7. 纯CSS,多个半圆以中心点旋转

    效果图: html代码: <div style=" background:#000; position: relative; width:300px; height:300px;&qu ...

  8. 洛谷 P2216 [HAOI2007]理想的正方形

    P2216 [HAOI2007]理想的正方形 题目描述 有一个a*b的整数组成的矩阵,现请你从中找出一个n*n的正方形区域,使得该区域所有数中的最大值和最小值的差最小. 输入输出格式 输入格式: 第一 ...

  9. [Xcode 实际操作]六、媒体与动画-(7)遍历系统提供的所有滤镜

    目录:[Swift]Xcode实际操作 本文将演示系统到底提供了多少滤镜供开发者使用,并了解每个滤镜都有哪些参数需要配置. 在项目导航区,打开视图控制器的代码文件[ViewController.swi ...

  10. 如何使用WPS从正文开始页码为1,而不是从目录开始?

    在插入目录前,在最前页插入一个空白页,在这个空白页里面生成目录,双击正文的页脚,点一下出现的与上一节相同的按钮,关闭页眉页脚的同前节,发现与上一节相同这几个字消失后,把目录中的页码删除,不会在影响正文 ...