Welcome to Subscribe On Youtube

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

  • 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;
        }
    };
    
    
  • 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
            )
    
    
  • 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 := 0
    
    	for _, x := range prices {
    		m = max(m, x)
    	}
    
    	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
        }
    }
    

All Problems

All Solutions