Clear Detailed Optimal Solution O(nlogn) (Python) 
IntuitionA key observation to solving this problem is as follows: If we only consider windows which start at the left endpoint of a segment or end at the right
# Intuition
A key observation to solving this problem is as follows: If we only consider windows which start at the left endpoint of a segment or end at the right endpoint of a segment, we are guaranteed to find the window with the max number of coins. **This window may not be uniquely optimal (e.g. there may be other windows which yield the same number of coins.**

Proof by contradiction:
- assume the optimal window does not start at the left endpoint of a segment and does not end at the right endpoint of a segment.
- if the window start is not contained in a segment, it can always be moved to the start of the nearest next segment without reducing coins.
- if the window end is not contained in a segment, it can always be moved to the end of the nearest previous segment without reducing coins.
- if both the window start and end are contained in segments but the window start is not at the left endpoint of the its segment and the window end is not at the right endpoint of its segment, we can either shift the window start to the left endpoint of its segment or shift the window end to the right endpoint of its segment without reducing the number of coin containing bags.
    - given the above, we can always either improve or maintain the number of coins in the window by making one of those two shifts. we should shift the window to include the bags containing more coins.

# Approach
Given the intuition above, we just need to implement a sliding window algorithm that checks all the relevant windows. We can check all windows that end at the right segment endpoints, and then by symmetry we can negate the number line and reuse the same helper function to check all windows that start at the left segment endpoints (equivalent to checking all windwos that end at the left segment endpoints on the reversed number line).

# Complexity
- Time complexity:
O(nlogn) where n is coins.length, due to sorting. Sliding window is O(n).

- Space complexity:
O(n) additional space to store coins on reversed number line. Possible
to optimize away this additional space to have constant additional space.

# Code
```python3 []
# - Sliding window two passes, ending at right and starting from left (equivalent to ending at left with all indices negated).
#   - maintain a start_idx initialized to 0 (refers to coins segment that contains the actual window start).
#   - maintain the current max, and current full segment coins.
#   - Iterate over coins, take the current interval as 
class Solution:
    def maximumCoins(self, coins: List[List[int]], k: int) -> int:
        reverse_number_line_coins = [[-r, -l, c] for l, r, c in coins]
        return max(self.sliding_window(coins, k), self.sliding_window(reverse_number_line_coins, k))

    def sliding_window(self, coins, k):
        """Returns the max coins from k bags, considering only windows that end at the right endpoints in coins."""
        coins.sort()
        max_coins = 0
        # full_segment_coins tracks coins in the window considering full segments ONLY! This is done so that
        # we can easily remove entire segments from full_segment_coins as we iterate.
        full_segment_coins = 0
        start_idx = 0
        for coin in coins:
            l, r, c = coin
            # add all coins from current coin segment.
            full_segment_coins += (r - l + 1) * c
            # remove all coins from previous coin segments that are no longer in the window.
            # condition is that right endpoint of previous coin segment is before window start.
            ls, rs, cs = coins[start_idx]
            while rs <= (r - k):
                full_segment_coins -= (rs - ls + 1) * cs
                start_idx += 1
                ls, rs, cs = coins[start_idx]
            # The segment corresponding to the current start_idx may only be partially in the window.
            window_start = r - k + 1
            segment_coins_before_window = max(0, window_start - ls) * cs
            max_coins = max(max_coins, full_segment_coins - segment_coins_before_window)
        return max_coins
```
['Python3']