100% Python3 || Dynamic Programming + Binary Search || EASY AND SIMPLE EXPLANATION (8 LINES)
Intuition\nI solved the problem Maximum events that can be attended II before attempting this so I already knew the approach. \n# Bottom Up Approach\n Sort the 
# Intuition\nI solved the problem ***Maximum events that can be attended II*** before attempting this so I already knew the approach. \n# Bottom Up Approach\n* Sort the array `rides`\n* keep a separate array `starts`\n* `n=len(rides)` NOT the same `n` given in the question, its useless\n* dp[index] indicates the max profit we can get when we are at index i in the rides array. (NOT AT THE iTH point in the road)\n* At each step we can either take the ride or skip it. If we take it we need to add the profit, if you dont we dont.\n* Every time we take the ride we need to find the next **VALID** start point for us. Since we have sorted the array, we can use binary search for this. We simple search in the `start` array for the index that immediately follows the current end given by `rides[i][1]`. `nextIndex = bisect.bisect_left(start,rides[i][1])` \n* We then use the above mentioned recurrence relation. `dp[i] = max(profit + dp[nextIndex], dp[i+1)`\n* If we dont take the ride we simply go to `i+1`. \n\n\n# Code\n```\nclass Solution:\n    def maxTaxiEarnings(self, n: int, rides: List[List[int]]) -> int:\n        rides.sort()\n        n = len(rides)\n        dp = [0]*(n+1)\n        start = [s for s,e,t in rides]\n\n        for i in range(n-1,-1,-1):\n            nextIndex = bisect_left(start,rides[i][1])\n            dp[i] = max(dp[i+1], rides[i][1]-rides[i][0]+rides[i][2] + dp[nextIndex])\n\n        return dp[0]\n```
['Python3']