|
| 1 | +# Time: O(n) |
| 2 | +# Space: O(n) |
| 3 | + |
| 4 | +import collections |
| 5 | + |
| 6 | + |
| 7 | +# freq table, prefix sum, combinatorics |
| 8 | +class Solution(object): |
| 9 | + def subsequencesWithMiddleMode(self, nums): |
| 10 | + """ |
| 11 | + :type nums: List[int] |
| 12 | + :rtype: int |
| 13 | + """ |
| 14 | + def nC2(x): |
| 15 | + return x*(x-1)//2 |
| 16 | + |
| 17 | + MOD = 10**9+7 |
| 18 | + result = 0 |
| 19 | + left = collections.defaultdict(int) |
| 20 | + right = collections.defaultdict(int) |
| 21 | + for x in nums: |
| 22 | + right[x] += 1 |
| 23 | + left_x_sq = 0 # sum(left[x]^2 for x != v) |
| 24 | + right_x_sq = sum(v**2 for v in right.itervalues()) # sum(right[x]^2 for x != v) |
| 25 | + left_x_right_x = 0 # sum(left[x]*right[x] for x != v) |
| 26 | + left_x_sq_right_x = 0 # sum(left[x]^2*right[x] for x != v) |
| 27 | + left_x_right_x_sq = 0 # sum(left[x]*right[x]^2 for x != v) |
| 28 | + for i, v in enumerate(nums): |
| 29 | + left_x_sq -= left[v]**2 |
| 30 | + right_x_sq -= right[v]**2 |
| 31 | + left_x_right_x -= left[v]*right[v] |
| 32 | + left_x_sq_right_x -= left[v]**2*right[v] |
| 33 | + left_x_right_x_sq -= left[v]*right[v]**2 |
| 34 | + right[v] -= 1 |
| 35 | + |
| 36 | + l, r = i, len(nums)-(i+1) |
| 37 | + # all possibles |
| 38 | + result += nC2(l)*nC2(r) |
| 39 | + # only mid is a |
| 40 | + result -= nC2(l-left[v])*nC2(r-right[v]) |
| 41 | + # bb/a/ac |
| 42 | + # sum((left[x]*(left[x]-1)//2)*right[v]*((r-right[v])-right[x]) for x != v) |
| 43 | + result -= ((left_x_sq-(l-left[v]))*(r-right[v])-(left_x_sq_right_x-left_x_right_x))*right[v]//2 |
| 44 | + # ac/a/bb |
| 45 | + # sum(left[v]*((l-left[v])-left[x])*(right[x]*(right[x]-1)//2) for x != v) |
| 46 | + result -= ((right_x_sq-(r-right[v]))*(l-left[v])-(left_x_right_x_sq-left_x_right_x))*left[v]//2 |
| 47 | + # ab/a/bc |
| 48 | + # sum(left[v]*left[x]*right[x]*((r-right[v])-right[x]) for x != v) |
| 49 | + result -= left[v]*left_x_right_x*(r-right[v])-left[v]*left_x_right_x_sq |
| 50 | + # bc/a/ab |
| 51 | + # sum(left[x]*((l-left[v])-left[x])*right[v]*right[x] for x != v) |
| 52 | + result -= right[v]*left_x_right_x*(l-left[v])-right[v]*left_x_sq_right_x |
| 53 | + # bb/a/ab |
| 54 | + # sum((left[x]*(left[x]-1)//2)*right[v]*right[x] for x != v) |
| 55 | + result -= right[v]*(left_x_sq_right_x-left_x_right_x)//2 |
| 56 | + # ab/a/bb |
| 57 | + # sum((right[x]*(right[x]-1)//2)*left[v]*left[x] for x != v) |
| 58 | + result -= left[v]*(left_x_right_x_sq-left_x_right_x)//2 |
| 59 | + |
| 60 | + left[v] += 1 |
| 61 | + left_x_sq += left[v]**2 |
| 62 | + right_x_sq += right[v]**2 |
| 63 | + left_x_right_x += left[v]*right[v] |
| 64 | + left_x_sq_right_x += left[v]**2*right[v] |
| 65 | + left_x_right_x_sq += left[v]*right[v]**2 |
| 66 | + return result % MOD |
0 commit comments