电梯 - dp - 单调队列

题目大意:总之就是有个 dp [ n ] = min ⁡ i = 0 n − 1 max ⁡ { dp , p [ i ] } + max ⁡ j = i + 1 n t [ j ] \text{dp}[n]=\min_{i=0}^{n-1} \max \{\text{dp},\text p[i]\}+\max_{j=i+1}^{n}\text t[j] dp[n]=mini=0n1max{dp,p[i]}+maxj=i+1nt[j]的dp,要做到线性求 d p [ n ] \text dp[n] dp[n]。保证 t t t是正整数, p p p是单调的, dp [ 0 ] = 0 \text{dp}[0]=0 dp[0]=0
题解:首先显然dp值是单调的,前面那个max可以分两部分讨论。其次若 t [ n ] ≥ t [ n − 1 ] t[n]\ge t[n-1] t[n]t[n1]那么 n − 1 n-1 n1 n n n一定在同一段里,因此 n − 1 n-1 n1就没有必要了,可以删掉。这样后面那个max也没有了。就直接单调队列即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define lint long long
#define fir first
#define sec second
namespace INPUT_SPACE{
    const int BS=(1<<24)+5;char Buffer[BS],*HD,*TL;inline int gc() { if(HD==TL) TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);return (HD==TL)?EOF:*HD++; }
    inline int inn() { int x,ch;while((ch=gc())<'0'||ch>'9');x=ch^'0';while((ch=gc())>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; }
}using INPUT_SPACE::inn;using namespace std;typedef pair<int,int> pii;
const int N=1000010;const lint INF=LLONG_MAX/100;pii p[N];lint val[N],f[N];int id[N],fp,rp;
inline int ins(int x) { lint v=f[x]+p[x+1].sec;while(rp>=fp&&val[rp]>=v) rp--;return val[++rp]=v,id[rp]=x; }
inline int del(int x) { return fp+=(fp<=rp&&id[fp]==x); } inline lint qry() { return fp<=rp?val[fp]:INF; }
int main()
{
    int n=inn(),m=0,j=0;fp=1,rp=0;rep(i,1,n) p[i].fir=inn(),p[i].sec=2*inn();sort(p+1,p+n+1);
    rep(i,1,n) { while(m&&p[i].sec>=p[m].sec) m--;p[++m]=p[i]; }
    rep(i,1,m) { for(ins(i-1);j<i&&f[j]<=p[i].fir;del(j++));f[i]=min((lint)p[i].fir+p[j].sec,qry()); }
    return !printf("%lld\n",f[m]);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值