题目

思路

首先按照\(t\)排序!!!!

首先考虑一个暴力\(dp\)

用\(f[i]\)表示前\(i\)个人到达地点所需要的时间。

那么就有如下的转移

\[f_i = min_{1 \le j \le i}(max(f_j,t_i) + max\{w_{j + 1} ... w_i\} * 2)
\]

这样复杂度是\(o(n^2)\)的

考虑优化上面的\(dp\)

因为已经按照\(t\)从小到大排过序了,所以如果\(w_i \le w_{i + 1}\)那么第\(i\)这个人就一定是和第\(i+1\)个人一起跟优秀。所以就可以把第\(i\)人剔除掉。

用单调栈可以完成上面的工作。

现在就变成了一个\(t\)单调递增,\(w\)单调递减的序列

然后再去看上面的\(dp\),我们可以把它分成两段。

\(if(f_j \le t_i)\)

\[f_i=t_i + max\{w_{j+1}...w_i\} * 2
\]

\(if(f_j > t_i)\)

\[f_i = f_j + max\{w_{j+1}...w_i\} * 2
\]

因为\(w\)数组单减,所以上面的式子\(max\{w_{j+1}...w_i\}\)是肯定是\(w_{j+1}\)。

所以上面的\(dp\)式子可以这样写

\(if(f_j \le t_i)\)

\[f_i=t_i + w_{j+1} * 2
\]

\(if(f_j > t_i)\)

\[f_i = f_j + w_{j+1} * 2
\]

因为\(f\)数组是递增的,所以第一种转移肯定一前一部分,第二种转移是后一部分。可以找到他们的分界点\(p\)

对于\(p\)及\(p\)之前的,因为\(t_i\)固定了,所以只要找到最小的\(w_{j + 1}\)就行了。显然\(w_{p+1}\)最小

对于\(p\)之后的,就是要找最小的\(f_j+w_{j+1}*2\),用线段树维护一下。

代码

/*
* @Author: wxyww
* @Date: 2019-03-24 19:59:19
* @Last Modified time: 2019-03-24 20:43:41
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const ll INF = 4e9,N = 1000000 + 100;
#define int ll
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int b[N],top,tree[N << 2], f[N];
struct node {
int p,w;
}a[N];
void update(int rt,int l,int r,int pos,int c) {
if(l == r) {
tree[rt] = c;
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(rt << 1,l,mid,pos,c);
else update(rt << 1 | 1,mid + 1,r,pos,c);
tree[rt] = min(tree[rt << 1],tree[rt << 1 | 1]);
}
int query(int rt,int l,int r,int L,int R) {
if(L <= l && R >= r) return tree[rt];
int mid = (l + r) >> 1;
int ans = INF;
if(L <= mid) ans = min(ans,query(rt << 1,l,mid,L,R));
if(R > mid) ans = min(ans,query(rt << 1 | 1,mid + 1,r,L,R));
return ans;
}
bool cmp(const node &A,const node &B) {
return A.p < B.p;
}
signed main() {
int n = read();
for(int i = 1;i <= n;++i) a[i].p = read(),a[i].w = read(); sort(a + 1,a + n + 1,cmp); for(int i = 1;i <= n;++i) {
while(a[i].w >= a[b[top]].w && top) top--;
b[++top] = i;
} int p = 0;
for(int i = 1;i <= top;++i) {
while(p < i - 1 && f[p + 1] <= a[b[i]].p) ++p;
f[i] = a[b[i]].p + a[b[p + 1]].w * 2;
if(p + 1 <= i - 1) f[i] = min(f[i],query(1,1,top,p + 1,i - 1));
update(1,1,top,i,f[i] + a[b[i + 1]].w * 2);
}
cout<<f[top];
return 0;
}

noi.ac89A 电梯的更多相关文章

  1. noi.ac #289. 电梯(单调队列)

    题意 题目链接 Sol 傻叉的我以为给出的\(t\)是单调递增的,然后\(100\rightarrow0\) 首先可以按\(t\)排序,那么转移方程为 \(f[i] = min_{j=0}^{i-1} ...

  2. NOI第一天感想&小结

    嘛...中午总算是到了深圳了--在虹桥机场和飞机上和市队大神们一起讨论各种各样奇(sang)葩(bing)的算(ren)法(lei)还是非常开心的,在此再各种膜拜一下尽管没来比赛的FFT大神@陈中瑞 ...

  3. 自己动手C#模拟电梯的运行V1.0

    电梯调度有很多种模式,参见http://www.cnblogs.com/jianyungsun/archive/2011/03/16/1986439.html 1.1先来先服务算法(FCFS) 先来先 ...

  4. 从一道NOI练习题说递推和递归

    一.递推: 所谓递推,简单理解就是推导数列的通项公式.先举一个简单的例子(另一个NOI练习题,但不是这次要解的问题): 楼梯有n(100 > n > 0)阶台阶,上楼时可以一步上1阶,也可 ...

  5. 浮动【电梯】或【回到顶部】小插件:iElevator.js

    iElevator.js 是一个jquery小插件,使用简单,兼容IE6,支持UMD和3种配置方式,比锚点更灵活. Default Options _defaults = { floors: null ...

  6. NOI 动态规划题集

    noi 1996 登山 noi 8780 拦截导弹 noi 4977 怪盗基德的滑翔翼 noi 6045 开餐馆 noi 2718 移动路线 noi 2728 摘花生 noi 2985 数字组合 no ...

  7. noi 6047 分蛋糕

    题目链接:http://noi.openjudge.cn/ch0405/6047/ 和Uva1629很类似,不过,可能用记忆化难写一点,状态初始化懒得搞了.就用循环好了. 状态描叙也可以修改,那个题目 ...

  8. Pair Project: Elevator Scheduler [电梯调度算法的实现和测试] --11061188刘强

    结对编程总结 队员:刘强(11061188) 林谋武(11061169) 结对编程: 结对编程的优点: 1.  两个人合作,相比于一个人自己奋斗而言,更能激发自己的潜能:我们在合作过程中,互相学习,互 ...

  9. 洛谷P1371 NOI元丹

    P1371 NOI元丹 71通过 394提交 题目提供者洛谷OnlineJudge 标签云端评测 难度普及/提高- 提交  讨论  题解 最新讨论 我觉得不需要讨论O long long 不够 没有取 ...

随机推荐

  1. Vmware安装CentOs7+gitlab(一)

    本篇文章主要介绍了VMware安装Centos7超详细过程(图文),具有一定的参考价值,感兴趣的小伙伴们可以参考一下 1.软硬件准备 软件:推荐使用VMwear,我用的是VMwear 12 镜像:Ce ...

  2. 三位数流水码的生成(000·····009··00A····00Z····ZZZ)

    //规格代码的生成 private String getCode (String code) { char[] chars=code.toCharArray(); if (chars[2]==57){ ...

  3. java反序列化漏洞实战

    准备: 域名一个,用于增加NS解析,判断是否存在反序列化漏洞. 公网IP服务器一台,用于搭建DNS代理,抓包判断. dnschef,DNS代理 ysoserial.jar生成payload. 简单的p ...

  4. pycharm中Django的安装和简单使用

    一.安装: 1.点击File,找到setting选项 2.点击+号,进入下面界面 结束后,安装完成 二.创建Django项目 创建成功后,新项目左侧: templates:用于存储HTML文件 set ...

  5. vue v-for动画bug

    因为是v-for 循环 出来的,:key = "index" 会出现问题,所以,需要把:key="XXX"换成其他属性就好了. 链接参考: https://se ...

  6. Unity 2D 效应器与来回移动的实现

    1.效应器 Point Effector 2D: 点效应器.进入区域,吸引或排斥物体 Area Effector 2D: 区域效应器,可以用来做马里奥的管道移动效果 Surface Effector ...

  7. 使用pyton在本地指定目录模拟服务器

    1.cd 到指定目录 2.运行命令 python 3之前 python -m SimpleHTTPServer & python 3+ python -m http.server & ...

  8. SQLServer之ISO游标使用

    什么是游标 结果集,结果集就是select查询之后返回的所有行数据的集合. 游标则是处理结果集的一种机制吧,它可以定位到结果集中的某一行,多数据进行读写,也可以移动游标定位到你所需要的行中进行操作数据 ...

  9. win10安装spacemacs

    参考: https://www.cnblogs.com/e190/p/10404927.html https://blog.csdn.net/u011729865/article/details/54 ...

  10. 如何使用java validation api进行参数校验----Hibernate-Validation

    在日常开发中,Hibernate Validator经常用来验证bean的字段,基于注解,方便快捷高效. 1. Bean Validation 中内置的 constraint 注解           ...