You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
3.7 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package class_2023_03_4_week;
import java.util.Arrays;
// 你驾驶出租车行驶在一条有 n 个地点的路上
// 这 n 个地点从近到远编号为 1 到 n ,你想要从 1 开到 n
// 通过接乘客订单盈利。你只能沿着编号递增的方向前进,不能改变方向
// 乘客信息用一个下标从 0 开始的二维数组 rides 表示
// 其中 rides[i] = [starti, endi, tipi]
// 表示第 i 位乘客需要从地点 starti 前往 endi
// 愿意支付 tipi 元的小费
// 每一位 你选择接单的乘客 i ,你可以 盈利 endi - starti + tipi 元
// 你同时 最多 只能接一个订单。
// 给你 n 和 rides ,请你返回在最优接单方案下,你能盈利 最多 多少元。
// 注意:你可以在一个地点放下一位乘客,并在同一个地点接上另一位乘客。
// 测试链接 : https://leetcode.cn/problems/maximum-earnings-from-taxi/
public class Code03_MaximumEarningsFromTaxi {
public static int MAXN = 100001;
public static long[] max = new long[MAXN << 2];
public static int n;
public static void build(int l, int r, int rt) {
if (l == r) {
max[rt] = 0;
} else {
int mid = (l + r) / 2;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
pushUp(rt);
}
}
public static long max(int r) {
if (r < 1) {
return 0;
}
return max(1, r, 1, n, 1);
}
private static long max(int L, int R, int l, int r, int rt) {
if (L <= l && r <= R) {
return max[rt];
}
int mid = (l + r) >> 1;
long ans = 0;
if (L <= mid) {
ans = Math.max(ans, max(L, R, l, mid, rt << 1));
}
if (R > mid) {
ans = Math.max(ans, max(L, R, mid + 1, r, rt << 1 | 1));
}
return ans;
}
public static void update(int index, long c) {
update(index, c, 1, n, 1);
}
private static void update(int index, long c, int l, int r, int rt) {
if (l == r) {
max[rt] = Math.max(max[rt], c);
} else {
int mid = (l + r) >> 1;
if (index <= mid) {
update(index, c, l, mid, rt << 1);
} else {
update(index, c, mid + 1, r, rt << 1 | 1);
}
pushUp(rt);
}
}
private static void pushUp(int rt) {
max[rt] = Math.max(max[rt << 1], max[rt << 1 | 1]);
}
public static long maxTaxiEarnings1(int len, int[][] rides) {
Arrays.sort(rides, (a, b) -> a[0] - b[0]);
n = len;
build(1, n, 1);
for (int[] ride : rides) {
long money = max(ride[0]) + ride[1] - ride[0] + ride[2];
update(ride[1], money);
}
return max(n);
}
public static int[] sorted = new int[MAXN];
public static long[] dp = new long[MAXN];
public static long maxTaxiEarnings2(int len, int[][] rides) {
int m = rides.length;
for (int i = 0, j = 0; i < m; i++) {
sorted[j++] = rides[i][0];
sorted[j++] = rides[i][1];
}
Arrays.sort(rides, (a, b) -> a[0] - b[0]);
Arrays.sort(sorted, 0, m << 1);
Arrays.fill(dp, 0, m << 1, 0);
int dpi = 0;
// pre : 讲的时候的max之前的最大收入
long pre = 0;
long ans = 0;
// 13 29 29 30 30 45
// 1 2 4 6
for (int[] ride : rides) {
int start = ride[0];
int end = ride[1];
int tips = ride[2];
// 29 -> 2
// 45 -> 6
int srank = rank(sorted, m << 1, start);
int erank = rank(sorted, m << 1, end);
// 70
// dp dp[0......70] max值之前的最大收入
while (dpi <= srank) {
pre = Math.max(pre, dp[dpi++]);
}
long money = pre + end - start + tips;
ans = Math.max(money, ans);
dp[erank] = Math.max(dp[erank], money);
}
return ans;
}
public static int rank(int[] sorted, int len, int num) {
int ans = 0;
int l = 0;
int r = len - 1;
int m = 0;
while (l <= r) {
m = (l + r) / 2;
if (sorted[m] >= num) {
ans = m;
r = m - 1;
} else {
l = m + 1;
}
}
return ans;
}
}