返回介绍

solution / 2900-2999 / 2921.Maximum Profitable Triplets With Increasing Prices II / README_EN

发布于 2024-06-17 01:02:58 字数 10966 浏览 0 评论 0 收藏 0

2921. Maximum Profitable Triplets With Increasing Prices II

中文文档

Description

Given the 0-indexed arrays prices and profits of length n. There are n items in an store where the ith item has a price of prices[i] and a profit of profits[i].

We have to pick three items with the following condition:

  • prices[i] < prices[j] < prices[k] where i < j < k.

If we pick items with indices i, j and k satisfying the above condition, the profit would be profits[i] + profits[j] + profits[k].

Return_ the maximum profit we can get, and _-1_ if it's not possible to pick three items with the given condition._

 

Example 1:

Input: prices = [10,2,3,4], profits = [100,2,7,10]
Output: 19
Explanation: We can't pick the item with index i=0 since there are no indices j and k such that the condition holds.
So the only triplet we can pick, are the items with indices 1, 2 and 3 and it's a valid pick since prices[1] < prices[2] < prices[3].
The answer would be sum of their profits which is 2 + 7 + 10 = 19.

Example 2:

Input: prices = [1,2,3,4,5], profits = [1,5,3,4,6]
Output: 15
Explanation: We can select any triplet of items since for each triplet of indices i, j and k such that i < j < k, the condition holds.
Therefore the maximum profit we can get would be the 3 most profitable items which are indices 1, 3 and 4.
The answer would be sum of their profits which is 5 + 4 + 6 = 15.

Example 3:

Input: prices = [4,3,2,1], profits = [33,20,19,87]
Output: -1
Explanation: We can't select any triplet of indices such that the condition holds, so we return -1.

 

Constraints:

  • 3 <= prices.length == profits.length <= 50000
  • 1 <= prices[i] <= 5000
  • 1 <= profits[i] <= 106

Solutions

Solution 1: Binary Indexed Tree

We can use two Binary Indexed Trees (BITs) to maintain the maximum profit on the left and right of each price, respectively. Then, we enumerate the middle price, query the maximum profit on both sides through the BIT, and finally take the maximum value.

The time complexity is $O(n \times \log M)$, and the space complexity is $O(M)$. Here, $n$ is the length of the array $prices$, and $M$ is the maximum value in the array $prices$. In this problem, $M \le 5000$.

class BinaryIndexedTree:
  def __init__(self, n: int):
    self.n = n
    self.c = [0] * (n + 1)

  def update(self, x: int, v: int):
    while x <= self.n:
      self.c[x] = max(self.c[x], v)
      x += x & -x

  def query(self, x: int) -> int:
    mx = 0
    while x:
      mx = max(mx, self.c[x])
      x -= x & -x
    return mx


class Solution:
  def maxProfit(self, prices: List[int], profits: List[int]) -> int:
    n = len(prices)
    left = [0] * n
    right = [0] * n

    m = max(prices)
    tree1 = BinaryIndexedTree(m + 1)
    tree2 = BinaryIndexedTree(m + 1)

    for i, x in enumerate(prices):
      left[i] = tree1.query(x - 1)
      tree1.update(x, profits[i])
    for i in range(n - 1, -1, -1):
      x = m + 1 - prices[i]
      right[i] = tree2.query(x - 1)
      tree2.update(x, profits[i])

    return max(
      (l + x + r for l, x, r in zip(left, profits, right) if l and r), default=-1
    )
class BinaryIndexedTree {
  private int n;
  private int[] c;

  public BinaryIndexedTree(int n) {
    this.n = n;
    c = new int[n + 1];
  }

  public void update(int x, int v) {
    while (x <= n) {
      c[x] = Math.max(c[x], v);
      x += x & -x;
    }
  }

  public int query(int x) {
    int mx = 0;
    while (x > 0) {
      mx = Math.max(mx, c[x]);
      x -= x & -x;
    }
    return mx;
  }
}

class Solution {
  public int maxProfit(int[] prices, int[] profits) {
    int n = prices.length;
    int[] left = new int[n];
    int[] right = new int[n];
    int m = 0;
    for (int x : prices) {
      m = Math.max(m, x);
    }
    BinaryIndexedTree tree1 = new BinaryIndexedTree(m + 1);
    BinaryIndexedTree tree2 = new BinaryIndexedTree(m + 1);
    for (int i = 0; i < n; ++i) {
      int x = prices[i];
      left[i] = tree1.query(x - 1);
      tree1.update(x, profits[i]);
    }
    for (int i = n - 1; i >= 0; --i) {
      int x = m + 1 - prices[i];
      right[i] = tree2.query(x - 1);
      tree2.update(x, profits[i]);
    }
    int ans = -1;
    for (int i = 0; i < n; ++i) {
      if (left[i] > 0 && right[i] > 0) {
        ans = Math.max(ans, left[i] + profits[i] + right[i]);
      }
    }
    return ans;
  }
}
class BinaryIndexedTree {
private:
  int n;
  vector<int> c;

public:
  BinaryIndexedTree(int n) {
    this->n = n;
    c.resize(n + 1, 0);
  }

  void update(int x, int v) {
    while (x <= n) {
      c[x] = max(c[x], v);
      x += x & -x;
    }
  }

  int query(int x) {
    int mx = 0;
    while (x > 0) {
      mx = max(mx, c[x]);
      x -= x & -x;
    }
    return mx;
  }
};

class Solution {
public:
  int maxProfit(vector<int>& prices, vector<int>& profits) {
    int n = prices.size();
    vector<int> left(n, 0);
    vector<int> right(n, 0);
    int m = *max_element(prices.begin(), prices.end());
    BinaryIndexedTree tree1(m + 1);
    BinaryIndexedTree tree2(m + 1);
    for (int i = 0; i < n; ++i) {
      int x = prices[i];
      left[i] = tree1.query(x - 1);
      tree1.update(x, profits[i]);
    }
    for (int i = n - 1; i >= 0; --i) {
      int x = m + 1 - prices[i];
      right[i] = tree2.query(x - 1);
      tree2.update(x, profits[i]);
    }
    int ans = -1;
    for (int i = 0; i < n; ++i) {
      if (left[i] > 0 && right[i] > 0) {
        ans = max(ans, left[i] + profits[i] + right[i]);
      }
    }
    return ans;
  }
};
type BinaryIndexedTree struct {
  n int
  c []int
}

func NewBinaryIndexedTree(n int) BinaryIndexedTree {
  c := make([]int, n+1)
  return BinaryIndexedTree{n: n, c: c}
}

func (bit *BinaryIndexedTree) update(x, v int) {
  for x <= bit.n {
    bit.c[x] = max(bit.c[x], v)
    x += x & -x
  }
}

func (bit *BinaryIndexedTree) query(x int) int {
  mx := 0
  for x > 0 {
    mx = max(mx, bit.c[x])
    x -= x & -x
  }
  return mx
}

func maxProfit(prices []int, profits []int) int {
  n := len(prices)
  left := make([]int, n)
  right := make([]int, n)
  m := slices.Max(prices)

  tree1 := NewBinaryIndexedTree(m + 1)
  tree2 := NewBinaryIndexedTree(m + 1)

  for i, x := range prices {
    left[i] = tree1.query(x - 1)
    tree1.update(x, profits[i])
  }

  for i := n - 1; i >= 0; i-- {
    x := m + 1 - prices[i]
    right[i] = tree2.query(x - 1)
    tree2.update(x, profits[i])
  }

  ans := -1

  for i := 0; i < n; i++ {
    if left[i] > 0 && right[i] > 0 {
      ans = max(ans, left[i]+profits[i]+right[i])
    }
  }

  return ans
}
class BinaryIndexedTree {
  private n: number;
  private c: number[];

  constructor(n: number) {
    this.n = n;
    this.c = Array(n + 1).fill(0);
  }

  update(x: number, v: number): void {
    while (x <= this.n) {
      this.c[x] = Math.max(this.c[x], v);
      x += x & -x;
    }
  }

  query(x: number): number {
    let mx = 0;
    while (x > 0) {
      mx = Math.max(mx, this.c[x]);
      x -= x & -x;
    }
    return mx;
  }
}

function maxProfit(prices: number[], profits: number[]): number {
  const n: number = prices.length;
  const left: number[] = Array(n).fill(0);
  const right: number[] = Array(n).fill(0);
  const m = Math.max(...prices);

  const tree1: BinaryIndexedTree = new BinaryIndexedTree(m + 1);
  const tree2: BinaryIndexedTree = new BinaryIndexedTree(m + 1);

  for (let i = 0; i < n; i++) {
    const x: number = prices[i];
    left[i] = tree1.query(x - 1);
    tree1.update(x, profits[i]);
  }

  for (let i = n - 1; i >= 0; i--) {
    const x: number = m + 1 - prices[i];
    right[i] = tree2.query(x - 1);
    tree2.update(x, profits[i]);
  }

  let ans: number = -1;

  for (let i = 0; i < n; i++) {
    if (left[i] > 0 && right[i] > 0) {
      ans = Math.max(ans, left[i] + profits[i] + right[i]);
    }
  }

  return ans;
}
struct BinaryIndexedTree {
  n: usize,
  c: Vec<i32>,
}

impl BinaryIndexedTree {
  fn new(n: usize) -> BinaryIndexedTree {
    BinaryIndexedTree {
      n,
      c: vec![0; n + 1],
    }
  }

  fn update(&mut self, x: usize, v: i32) {
    let mut x = x;
    while x <= self.n {
      self.c[x] = self.c[x].max(v);
      x += x & x.wrapping_neg();
    }
  }

  fn query(&self, x: usize) -> i32 {
    let mut x = x;
    let mut mx = 0;
    while x > 0 {
      mx = mx.max(self.c[x]);
      x -= x & x.wrapping_neg();
    }
    mx
  }
}

impl Solution {
  pub fn max_profit(prices: Vec<i32>, profits: Vec<i32>) -> i32 {
    let n = prices.len();
    let mut left = vec![0; n];
    let mut right = vec![0; n];
    let m = prices.iter().cloned().max().unwrap_or(0);

    let mut tree1 = BinaryIndexedTree::new((m as usize) + 1);
    let mut tree2 = BinaryIndexedTree::new((m as usize) + 1);

    for i in 0..n {
      let x = prices[i] as usize;
      left[i] = tree1.query(x - 1);
      tree1.update(x, profits[i]);
    }

    for i in (0..n).rev() {
      let x = (m + 1 - prices[i]) as usize;
      right[i] = tree2.query(x - 1);
      tree2.update(x, profits[i]);
    }

    let mut ans = -1;
    for i in 0..n {
      if left[i] > 0 && right[i] > 0 {
        ans = ans.max(left[i] + profits[i] + right[i]);
      }
    }

    ans
  }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文