专栏文章
题解:P11598 [NOISG 2018 Finals] Safety
P11598题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minhjzn0
- 此快照首次捕获于
- 2025/12/02 02:31 3 个月前
- 此快照最后确认于
- 2025/12/02 02:31 3 个月前
思路
首先我们写出朴素 dp:设 表示已经放好前 个位置,第 个位置的高度是 的最小代价。
那么转移就是:。然后不难发现,这个东西是下凸的。可以尝试使用 slope trick 做。
我们观察该 dp 的定义域与斜率的值域。发现定义域很大,但斜率的值域并不大,所以我们考虑维护拐点。
用 slope trick 做第一步应当先把式子拆成几部分,并观察这几部分在函数上的影响。
所以我们拆成 和 两步来看。
不难发现第一步就是,把最低段的左端点和右端点往两边扩展 。
第二也是显然且套路的,相当于往函数上加一个 V 状物。那我们直接把 左边的部分斜率全部 ,右边的部分斜率全部 即可。
于是我们维护对顶堆。那么操作一就是直接对两个堆打标记,操作二就是在某个堆插入两个 并把这个堆的堆顶转移到另一个堆。
代码
CPP#include<bits/stdc++.h>
#define int long long
#define N 1000005
#define mod 998244353
#define pii pair<int,int>
#define x first
#define y second
#define pct __builtin_popcount
#define mpi make_pair
#define inf 2e18
using namespace std;
int T=1,n,h,a[N];
void solve(int cs){
if(!cs)return;
cin>>n>>h;
for(int i=1;i<=n;i++){
cin>>a[i];
}
priority_queue<int>q1;
priority_queue<int,vector<int>,greater<int>>q2;
int t1=0,t2=0;
q1.push(a[1]);
q2.push(a[1]);
int res=0;
for(int i=2;i<=n;i++){
t1-=h;
t2+=h;
if(a[i]>=q1.top()+t1&&a[i]<=q2.top()+t2){
q1.push(a[i]-t1);
q2.push(a[i]-t2);
}
else if(a[i]<q1.top()+t1){
res+=q1.top()+t1-a[i];
q1.push(a[i]-t1);
q1.push(a[i]-t1);
q2.push(q1.top()+t1-t2);
q1.pop();
}
else{
res+=a[i]-q2.top()-t2;
q2.push(a[i]-t2);
q2.push(a[i]-t2);
q1.push(q2.top()+t2-t1);
q2.pop();
}
}
cout<<res<<'\n';
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
// cin>>T;
// init(3e5);
for(int cs=1;cs<=T;cs++){
solve(cs);
}
// cerr<<clock()*1.0/CLOCKS_PER_SEC<<'\n';
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...