搭积木(block)
【问题描述】
小 OY 是一个喜欢搭积木的孩子,他有一天决定向小 C 展示他特别的搭积木
技巧。
现在一条直线上从左到右有 n 个位置,标号 1..n,第 i 个位置坐标为 x_i。
每个位置上都预先叠好了一些积木,其中第 i 个位置上叠了 a_i 块积木。
小 OY 一开始会向小 C 指定 1..n 中的某个位置 s,然后,他在第 0 秒从位置
s 出发,开始搭积木。
他可以做这些动作:
1、向左移动 1 个单位坐标,用时 1 秒。
2、向右移动 1 个单位坐标,用时 1 秒。
3、从当前位置顶部拿起一块积木,瞬间完成。
4、把拿着的积木叠到当前位置,瞬间完成。
由于小 OY 很小,任意时刻他手上至多只能带一块积木。
当时间到达第 T 秒时,小 OY 不会再进行移动。这时候,如果位置 s 的积木
叠得越高,就显得小 OY 叠积木本领越强。
现在,小 OY 在思考,如果他的移动策略足够高明,并且位置 s 也选定得恰
到好处,那么第 T 秒时位置 s 最多能叠到多少块积木呢?
【输入】
输入文件名:block.in
第一行两个数 n、T。
第二行 n 个严格递增的整数,第 i 个数为 x_i。
第三行 n 个非负整数,第 i 个数为 a_i。
【输出】
输出文件名:block.out
第一行一个数,为从最优的 s 出发在最高明的移动策略下,第 T 秒位置 s 至
多能叠到多少块积木。
【数据范围】
测试点 1..3:n≤100,T≤1000
测试点 4..5:a_i≤1
测试点 6..7:x_i = i
测试点 1..8:n≤10 5
测 试点 1..10: 1≤n≤ 5*10 5 ,0≤ T≤ 10 18 ,0≤ a_i≤10 4 ,0 ≤ x_i≤10 9
算法 1
先枚举 s,然后从近到远把其他位置的积木一个个拿到 s 来,直到时间 T 耗尽
为止。复杂度 O(nT)。
算法 2
优化一下算法 1,假设当前取到的最左、最右位置分别为 l、r,然后每次一下
取 min(a[l],a[r])个,如果取完后时间不超过 T 就取完,否则直接计算还能取几
个。由于每次左右指针都至少有一个会往边界移,复杂度 O(n^2)。
算法 3
先二分答案 k,问题成了:求把位置 s 叠到高度 k 所需的最短时间。
从左到右枚举 s,那么肯定是从前 k 近的地方搬来积木。我们想象每个位置 i
的 a[i]个积木是从左到右紧密排列在坐标 x[i]的,令 l 表示前 k 近的积木最左的
那块,r 表示最右的那块,随着 s 的右移,左边的积木们越来越远,右边的越来越
近,那么 l、r 是非降的。
暴力移动指针的话,复杂度是 O(Σ a[i])的。
正解:
在算法3的基础上如果时间不超过就尽可能取完,因为l,r非降,所以可以用
类似单调队列的思想,移动左右
lc表示a[l]未取的积木,rc表示a[r]已取的积木
先得出把1堆到k的最短时间,得到r和rc
之后考虑把s位置右移,右移后在不考虑l,r的移动的情况下
等价于把1~i的积木右移,i+1~r的积木向右撤回
移动完更新时间后,如果l比r距离s远,那么不如把l积木不取,来取r的积木
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int n;
ll a[],x[];
ll s[],T,ans;
ll sum(int l,int lc,int r,int rc)
{
if (l==r)
return rc-lc;
return (s[r-]-s[l]+a[l]-lc+rc);
}
bool check(ll need)
{int i;
int l=,r=n+;
ll lc=,rc=;
ll s=;
ll cur=;
for (i=;i<=n;i++)
{
if (s+a[i]<=need)
{s+=a[i];cur+=(x[i]-x[])*a[i];}
else
{
rc=need-s;r=i;cur+=(x[i]-x[])*rc;
break;
}
}
if (cur<=T) return ;
for (i=;i<=n;i++)
{
cur+=(x[i]-x[i-])*(sum(l,lc,i,)-sum(i,,r,rc));
while (r<=n&&(x[i]-x[l])>(x[r]-x[i]))
{
int p=min(a[l]-lc,a[r]-rc);
cur+=(x[r]-x[i]-x[i]+x[l])*p;
lc+=p;rc+=p;
if (lc>=a[l]) l++,lc=;
if (rc>=a[r]) r++,rc=;
}
if (cur<=T) return ;
}
return ;
}
int main()
{int i;
cin>>n>>T;
T/=;
for (i=;i<=n;i++)
{
scanf("%lld",&x[i]);
}
for (i=;i<=n;i++)
{
scanf("%lld",&a[i]);
s[i]=s[i-]+a[i];
}
ll l=,r=s[n];
while (l<=r)
{
ll mid=(l+r)/;
if (check(mid)) ans=mid,l=mid+;
else r=mid-;
}
cout<<ans;
}
搭积木(block)的更多相关文章
- Leo 搭积木
Leo 搭积木[问题描述]Leo是一个快乐的火星人,总是能和地球上的 OIers玩得很 high.2012 到了, Leo 又被召回火星了,在火星上没人陪他玩了,但是他有好多好多积木,于是他开始搭积木 ...
- Android_就像小朋友“搭积木”一样。
就像小朋友“搭积木”一样.感觉这句话很有意思.完整的话是这样的: Android提供了大量功能丰富的UI组件,开发者只要按一定规律把这些UI组件组合起来 --就像小朋友“搭积木”一样,把这些UI组件搭 ...
- XJOI1657&Codevs1255搭积木【树状动规】
搭积木 一种积木搭建方式,高为H的积木,最底层有M个积木,每一层的积木数是他的低一层的积木数+1或-1.总共有N个积木.(且每行积木数不超过10)比如上图N=13 H=6 M=2. 输入格式: 第一行 ...
- 蓝桥杯-搭积木-java
/* (程序头部注释开始) * 程序的版权和版本声明部分 * Copyright (c) 2016, 广州科技贸易职业学院信息工程系学生 * All rights reserved. * 文件名称: ...
- codevs 3249 搭积木
提交地址:http://codevs.cn/problem/3249/ 3249 搭积木 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目 ...
- [Luogu 2816]宋荣子搭积木
Description saruka非常喜欢搭积木,他一共有n块积木.而且saruka的积木很特殊,只能一块块的竖着摞,可以摞很多列.说过saruka的是特殊的积木了,这些积木都非常智能,第i块积木有 ...
- 搭积木(java)-蓝桥杯
搭积木小明最近喜欢搭数字积木,一共有10块积木,每个积木上有一个数字,0~9.搭积木规则:每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小.最后搭成4层的金字塔形,必须用完所有的积木.下 ...
- 《陪孩子像搭积木一样学编程》,一起来玩Scratch(1)使用Scratch编程的基本流程
编程是一件很有趣的事情.初次接触编程,你可能不知所措,别担心,这并不复杂.首先,为了让读者对编程有大概的了解,可以把编写Scratch程序的过程分成7个步骤(如图1.8).注意,这是理想状态.在实际的 ...
- 整数N分解,搭积木,离散数学中的母函数,ZOJ(1163)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1163 解题报告: 将整数N分解为:两个及以上的不重复的整数,最流 ...
随机推荐
- 20145237 实验一 逆向与Bof基础
20145237 实验一 逆向与Bof基础 1.直接修改程序机器指令,改变程序执行流程 此次实验是下载老师传给我们的一个名为pwn1的文件. 首先,用 objdump -d pwn1 对pwn1进行反 ...
- 十款不容错过的Swift iOS开源项目及介绍
1.十款不容错过的Swift iOS开源项目. http://www.csdn.net/article/2014-10-16/2822083-swift-ios-open-source-project ...
- Mysql数据库的触发程序
/** **创建表 */ CREATE TABLE test1(a1 INT); CREATE TABLE test2(a2 INT); CREATE TABLE test3(a3 INT NOT N ...
- a标签传递参数
a标签传递参数 单个参数:参数名称前面跟 ? <a href="localhost:8080/arguments?id=1">单个参数</a> 多个参数 ...
- vue初尝试--新建项目
这是一篇技术贴--如何新建一个基于vue的项目 1.下载对应版本的nodejs安装,下载的nodejs都集成了npm,所以nodejs安装完成之后npm也对应安装完成了. 安装完成之后可以在cmd命令 ...
- 使用 Vue 和 epub.js 制作电子书阅读器
ePub 简介 ePub 是一种电子书的标准格式,平时我看的电子书大部分是这种格式.在手机上我一般用"多看"阅读 ePub 电子书,在 Windows 上找不到用起来比较顺心的软件 ...
- ArrayList源码学习----JDK1.7
什么是ArrayList? ArrayList是存储一组数据的集合,底层也是基于数组的方式实现,实际上也是对数组元素的增删改查:它的主要特点是: 有序:(基于数组实现) 随机访问速度快:(进行随机访问 ...
- Python内置函数(37)——sorted
英文文档: sorted(iterable[, key][, reverse]) Return a new sorted list from the items in iterable. Has tw ...
- java基础复习(1)
用记事本写java文件 打开记事本,编写java文件,需要注意文件名与类名要相同 注意文件的后缀名(也叫拓展名)改为.java java对大小写是敏感的 public class nihao{\ pu ...
- istio入门(04)istio的helloworld-部署构建
参考链接: https://zhuanlan.zhihu.com/p/27512075 安装Istio目前仅支持Kubernetes,在部署Istio之前需要先部署好Kubernetes集群并配置好k ...