原题目
问题描述
小H最近迷上了一款叫做“超级跳”的休闲游戏。
游戏中,有n层云朵。你控制一个小人,出生在第n层云朵上,目标是不断向下跳,最终抵达地面。为了方便,这里对游戏做一些简化。
如果建立平面坐标系,可以将每层云朵抽象成一条平行于x轴的线段。第i层云朵可以抽象成一条纵坐标等于i,左右端点的横坐标分别是li和ri的线段。
小人可以抽象成一个点,出生点坐标是(s, n),保证在第n层云朵上。每次操作,在不越出云朵边界的前提下,你可以控制小人向左移动1单位距离,耗费时间是p;也可以控制小人向右移动1单位距离,耗费时间是q。如果小人处在云朵的边缘(即坐标与线段端点重合),你可以控制它向下跳,那么它将一直坠落到最近的一层云朵或者地面(如果下面没有云朵)上,坠落耗费的时间等于下落的高度。特别地,如果某次下落的高度大于h,小人就会死掉,游戏失败。当小人成功落到地面(即x轴)上时,你就顺利通关了。
这一次,小H尝试了无数次仍无法在时限内通过某关。你能帮助他吗?
输入格式
第一行,五个整数n,s,h,p,q。
接下来n行,每行两个整数li和ri,依次表示每层云朵的左右端点的横坐标。
输出格式
输出一个整数,表示小人降落到地面最少花费的时间。
如果不可能成功降落到地面,输出-1。
样例输入
4 0 2 1 1
-2 1
-1 2
-3 0
-2 1
样例输出
6
样例说明
如上图。出生在S点,先向右移动1单位,向下跳到第2层云朵上,再向右移动1单位,再向下跳,就降落到地面上了。这也是耗时最少的方案。
数据规模和约定
40%的数据中,1 ≤n≤ 100。
100%的数据中,1 ≤n, h≤10^5,1 ≤p, q ≤10,-10^5≤li≤ri≤10^5,ln≤s≤rn。
解答
设
fli,fri,fP
分别为第
i
层左端和右端和点
其中 tl 为第 i 层左端点竖直向下落到的点,
在层内走是很容易算出来的,在此就不做叙述。
我们只需要知道如何用
于是想到用线段树覆盖,从最底层做起,每上升一层,将这一层覆盖到线段树上,之后只需看 i <script id="MathJax-Element-1119" type="math/tex">i</script>横坐标向下最后覆盖的是那一层即可。
这里线段树可以用map来实现,可以减少打量代码。
参考代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <map>
#include <queue>
#include <fstream>
using namespace std;
ifstream cin("jump.in");
ofstream cout("jump.out");
typedef long long ll;
typedef map<int, int>::iterator it;
map<int, int> tree;
int et = -1;
int n, h, s, p, q;
int l[100050], r[100050], ml = 1000000;
ll f[500050][2];
void insert(int i, int l, int r) {
it st, th;
st = tree.lower_bound(l);
th = tree.upper_bound(r);
int tmp = (--th)->second;
tree.erase(st, ++th);
tree[l] = i;
tree[r] = tmp;
}
int getlastest(int Point) {
int j = (--tree.upper_bound(Point))->second;
return j;
}
void readin() {
cin >> n >> s >> h >> p >> q;
for (int i = 1; i <= n; i++) {
cin >> l[i] >> r[i];
ml = min(ml, l[i]);
}
}
void work() {
memset(head, -1, sizeof(head));
tree[ml] = 0;
int tmp;
for (int i = 1; i <= n; i++) {
f[i][0] = f[i][1] = 1000000000000ll;
tmp = getlastest(l[i]);
if (tmp == 0) {
if (i <= h) {
f[i][0] = i;
}
} else {
if (i - tmp <= h) {
f[i][0] = min(f[tmp][0] + (ll)(i - tmp) + (ll)(l[i] - l[tmp]) * (ll)p, f[tmp][1] + (ll)(i - tmp) + (ll)(r[tmp] - l[i]) * (ll)q);
}
}
tmp = getlastest(r[i]);
if (tmp == 0) {
if (i <= h) {
f[i][1] = i;
}
} else {
if (i - tmp <= h) {
f[i][1] = min(f[tmp][0] + (ll)(i - tmp) + (ll)(r[i] - l[tmp]) * (ll)p, f[tmp][1] + (ll)(i - tmp) + (ll)(r[tmp] - r[i]) * (ll)q);
}
}
insert(i, l[i], r[i]+1);
}
ll ans = min(f[n][0] + (ll)(s - l[n]) * (ll)p, f[n][1] + (ll)(r[n] - s) * (ll)q);
if (ans >= 1000000000000ll) {
cout << "-1";
} else {
cout << ans;
}
}
int main() {
ios::sync_with_stdio(false);
readin();
work();
return 0;
}