O(Nlog(N)) python solution explained
Sort the envelopes first by increasing width. For each block of same-width envelopes, sort by decreasing height.\n\nThen find the longest increasing subsequence
Sort the envelopes first by increasing width. For each block of same-width envelopes, sort by decreasing height.\n\nThen find the longest increasing subsequence of heights.\n\nSince each same-width subarray is non-increasing  in height, we can never pick more than one height within each width (otherwise heights would be non-increasing)\n\nThus, the resulting longest increasing heights subsequence is also increasing in width.\n\nExample:\n\n**input**\n\n    [[5,4],[6,4],[6,7],[2,3]]\n\nsort by increasing widths, then decreasing heights:\n\n    [[2,3],[5,4],[6,7],[6,4]]\n\nGet the heights:\n\n    [3,4,7,4]\n\nFind the length longest increasing subsequence:\n\n    [3,4,7]\n\n(Note that we could not have picked more than one evelope with width 6)\n\nAnswer: 3\n```\nclass Solution(object):\n    def maxEnvelopes(self, envs):\n        """\n        :type envelopes: List[List[int]]\n        :rtype: int\n        """\n        # sort first by increasing width\n        # within each subarray of same-width envelopes\n        # sort by decreasing height\n        envs.sort(key=lambda (w,h): (w,-h))\n        \n        # now find the length of the longest increasing subsequence of heights.\n        # Since each same-width block was sorted non-increasing, \n        # we can only pick at most one height within each block\n        # otherwise, the sequence would be non-increasing\n        tails=[]\n        for (w,h) in envs:\n            idx=bisect.bisect_left(tails, h)\n            if idx==len(tails):\n                tails.append(h)                        \n            elif idx==0 or tails[idx-1]<h:\n                tails[idx]=h\n        return len(tails)    \n```
[]