LG3195 [HNOI2008]玩具装箱TOY
题意
P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京。他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中。P教授有编号为\(1\cdots N\)的\(N\)件玩具,第\(i\)件玩具经过压缩后变成一维长度\(C_i\).为了方便整理,P教授要求在一个一维容器中的玩具编号是连续的。同时如果一个一维容器中有多个玩具,那么两件玩具之间要加入一个单位长度的填充物,形式地说如果将第\(i\)件玩具到第\(j\)个玩具放到一个容器中,那么容器的长度将为\(x=j-i+\sum\limits_{k=i}^{j}C_k\)制作容器的费用与容器的长度有关,根据教授研究,如果容器长度为\(x\),其制作费用为\((X-L)^2\).其中\(L\)是一个常量。P教授不关心容器的数目,他可以制作出任意长度的容器,甚至超过\(L\)。但他希望费用最小.
\(N \leq 50000\)
分析
明显的dp,\(dp[i]\)表示前\(i\)个的最小花费。
\[
dp[i]=\min_{j<i} \{ dp[j]+(i-j-1+c[i]-c[j]-L)^2 \}
\]
其中\(c\)表示前缀和。
然后呢?拆开?
其实我开始是这么想的。然后看了一下题解,发现可以发挥信息学的优势。令\(a[i]=i+c[i]-L-1,b[i]=c[i]+i\),那么就很简单了。
令\(j>k\),且\(j\)比\(k\)优,则
\[
\frac{dp[j]+b[j]^2-dp[k]-b[k]^2}{b[j]-b[k]}<2a[i]
\]
小于单调增,下凸包+单调队列。
时间复杂度\(O(n)\)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
rg T data=0;
rg int w=1;
rg char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
w=-1;
ch=getchar();
}
while(isdigit(ch))
{
data=data*10+ch-'0';
ch=getchar();
}
return data*w;
}
template<class T>T read(T&x)
{
return x=read<T>();
}
using namespace std;
typedef long long ll;
co int N=5e4+2;
ll c[N];
ll a[N],b[N];
ll dp[N];
ll Up(int j,int k)
{
return dp[j]+b[j]*b[j]-dp[k]-b[k]*b[k];
}
ll Down(int j,int k)
{
return b[j]-b[k];
}
ll Cal(int i,int j)
{
return dp[j]+a[i]*a[i]-2*a[i]*b[j]+b[j]*b[j];
}
int q[N];
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
int n=read<int>(),L=read<int>();
for(int i=1;i<=n;++i)
{
c[i]=c[i-1]+read<int>();
a[i]=i+c[i]-L-1;
b[i]=c[i]+i;
}
int head=0,tail=0;
q[tail++]=0;
for(int i=1;i<=n;++i)
{
while(head+1<tail&&Up(q[head+1],q[head])<=2*a[i]*Down(q[head+1],q[head]))
++head;
dp[i]=Cal(i,q[head]);
while(head+1<tail&&Up(i,q[tail-1])*Down(q[tail-1],q[tail-2])<=Up(q[tail-1],q[tail-2])*Down(i,q[tail-1]))
--tail;
q[tail++]=i;
}
printf("%lld\n",dp[n]);
return 0;
}
LG3195 [HNOI2008]玩具装箱TOY的更多相关文章
- BZOJ 1010: [HNOI2008]玩具装箱toy [DP 斜率优化]
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 9812 Solved: 3978[Submit][St ...
- BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP
1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...
- 【bzoj1010】[HNOI2008]玩具装箱toy
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 9281 Solved: 3719[Submit][St ...
- 【BZOJ 1010】 [HNOI2008]玩具装箱toy (斜率优化)
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 9330 Solved: 3739 Descriptio ...
- bzoj 1010 [HNOI2008]玩具装箱toy(DP的斜率优化)
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7874 Solved: 3047[Submit][St ...
- BZOJ 1010 [HNOI2008]玩具装箱toy
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 7184 Solved: 2724[Submit][St ...
- bzoj1010[HNOI2008]玩具装箱toy 斜率优化dp
1010: [HNOI2008]玩具装箱toy Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 11893 Solved: 5061[Submit][S ...
- P3195 [HNOI2008]玩具装箱TOY(斜率优化dp)
P3195 [HNOI2008]玩具装箱TOY 设前缀和为$s[i]$ 那么显然可以得出方程 $f[i]=f[j]+(s[i]-s[j]+i-j-L-1)^{2}$ 换下顺序 $f[i]=f[j]+( ...
- [luogu P3195] [HNOI2008]玩具装箱TOY
[luogu P3195] [HNOI2008]玩具装箱TOY 题目描述 P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆, ...
随机推荐
- FIFO设计验证经验谈
概述: FIFO是电路设计中非常重要的一个基本电路.一般的超大规模集成电路中,都会用到FIFO.所以,FIFO是每个SOC设计和验证工程师必须掌握的一种核心电路. FIFO电路又分为异步FIFO和同步 ...
- length与size()
List li = new ArrayList(20);System.out.println(li.size()) ;// 0 int [] arr = new int [20];System.ou ...
- 20145109 《Java程序设计》第八周学习总结
Chapter 15 API java.util.logging package The constructor of Logger class is protected. If Logger ins ...
- GIT生成 SSH Key步骤
//设置user.name和email 提交到git之后会显示用户名(在随意一个目录打开git-bash执行就行)Administrator@DESKTOP-BP3H0HS MINGW64 /d/mi ...
- LeetCode——Add Strings
LeetCode--Add Strings Question Given two non-negative integers num1 and num2 represented as string, ...
- PHP 404伪装
<?php function GetCurUrl() { if(!empty($_SERVER["REQUEST_URI"])) { $scriptName = $_SERV ...
- JumpGame,JumpGame2
JumpGame:给定一个非负整数数组,开始在第一个位置,每个位置上的数字代表最大可以跳跃的步数,判断能不能跳到最后一个位置. 例如:A=[2,3,1,1,4],在位置0处,可以跳一步到位置1,位置1 ...
- MySQL主从配置实现(同一台主机)
////////////////////MySQL主从(同一台主机)////////////////////// 1.安装配置MySQL参考之前步骤搭建MySQL服务为了做实验方便,我们在同一台机器上 ...
- Gradle 一(Android)
参考一:Gradle 完整指南(Android) 参考二:深入理解Android(一):Gradle详解 参考三:Gradle for Android 第一篇( 从 Gradle 和 AS 开始 ) ...
- dga 分析
02n-0iy6gn3ozzwmyu.7i43n9qil1g1z2-.com0e527eaf_5ec5_4623_9fe9_e459583acd72.com0fmgm1cuu7h1279dghgka0 ...