Since I could not completely understand David's answer I have used what I understood from it and then wrote a complete function to calculate the result with his ideas. I'm not convinced what he says at the end is fully correct as I had to use formulas that were sort of similar but not exactly, and I can't see how they are equivalent.
I will put in the code then explain
class Node: def __init__(self, value = None, index=0): self.index = index self.parent = 0 self.left = 0 self.right = 0 self.value = value tree = [] tree.append(Node(0)) for i in range(1,len(int_array)+1): k = i - 1 tree.append(Node(int_array[i-1],i-1)) while(tree[k].value > tree[i].value): k = tree[k].parent tree[i].left = tree[k].right tree[k].right = i tree[i].parent = k tree[tree[i].left].parent = i
So first I used the treap like David suggested and essentially copied the implementation of that from OI Wiki. Now for the function itself.
total_weird_sum = 0 def weird_sum(node, total_weird_sum): if(node.left == 0 and node.right == 0): total_weird_sum += node.value**2 return 1, node.value, node.value, total_weird_sum if(node.left==0): left_length, left_value_sum, left_value_sequence_sum = 0, 0, 0 else: left_length, left_value_sum, left_value_sequence_sum, total_weird_sum = weird_sum(tree[node.left], total_weird_sum) if(node.right==0): right_length, right_value_sum, right_value_sequence_sum = 0,0, 0 else: right_length, right_value_sum, right_value_sequence_sum, total_weird_sum = weird_sum(tree[node.right], total_weird_sum) total_weird_sum += node.value*right_value_sequence_sum*(left_length+1) + node.value*left_value_sequence_sum*(right_length+1) + (right_length+1)*(left_length+1)*node.value**2 if(node.parent==0): return total_weird_sum value_sum = left_value_sum + right_value_sum + node.value length = right_length+left_length+1 if(node.index > tree[node.parent].index): value_sequence_sum = (length+1)*(left_value_sum) - left_value_sequence_sum + right_value_sequence_sum + (right_length+1)*node.value else: value_sequence_sum = (length+1)*(right_value_sum) - right_value_sequence_sum + left_value_sequence_sum + (left_length+1)*node.value return length, value_sum, value_sequence_sum, total_weird_sum
It is a recursive function, again as David suggested. Let me use as the example the treap structure from David's example.
1 / \ 3 2 / \ 4 6 \ 5 \ 9
First, let's calculate the end children contribution. Since they are just single element sub-arrays a number a will contribute a**2 to the answer. The code in the lines
if(node.left == 0 and node.right == 0): total_weird_sum += node.value**2 return 1, node.value, node.value, total_weird_sum
adds this to the weird sum and then also returns the length of that set, 1, the value a twice (explained in a minute). So 9 contributes 9**2.
Now for the next subarray which is [5,9], the subarrays are [5] and [5,9]. To explain what David put further with his example of
a b x c d e
if x is the smallest then the number of occurrences of x is the number of elements left of x, plus 1 (left length + 1) multiplied by the same on the right, or (left length + 1)(right length + 1). For the other numbers it is the number of steps from the edges to the number multiplied by the other length + 1. So b is 2*4 occurrences. We combine the sum of the left and right elements weighed by their contribution with the value sequence sum. The right value sequence sum is 3*c + 2*d + e
Thus in the code
if(node.left==0): left_length, left_value_sum, left_value_sequence_sum = 0, 0, 0 else: left_length, left_value_sum, left_value_sequence_sum, total_weird_sum = weird_sum(tree[node.left], total_weird_sum) if(node.right==0): right_length, right_value_sum, right_value_sequence_sum = 0,0, 0 else: right_length, right_value_sum, right_value_sequence_sum, total_weird_sum = weird_sum(tree[node.right], total_weird_sum) total_weird_sum += node.value*right_value_sequence_sum*(left_length+1) + node.value*left_value_sequence_sum*(right_length+1) + (right_length+1)*(left_length+1)*node.value**2
The children that are empty contribute nothing, while the return of the function is value sequence sum and the ordinary value sum from the node and all its children. The right value sequence sum at node 4 is 2*5 + 9, for example, while the ordinary sum is 5+9. This is multiplied by the left length + 1 (1) and by the node value 4. The same happens for the other child but in this case it contributes nothing. Also, (left_length + 1)(right_length +1)*node.value contributes the one element subarray of the node to weird sum.
Now for the trickier part. As we move from a child to its parent, we want to combine the all the nodes descended from the child into one effective sequence. The correct way for the example above to node 2 is
1 / \ 3 2 / \ 9 6 / 5 / 4
as in our original array is 9 closest to 5. You can imagine rotating the right branch about 4 counterclockwise towards 2. The right value sequence sum has to be adjusted now to account for the change in order. The original ones were 2*5+9 and now it must be 3*9 + 2*5 + 4. To do this, if the parent node is on the right, we take the right value sum (5+9) and multiply it by the number of nodes including the parent + 1 (2+1+1) then remove the current right value sequence sum and add the left value sequence sum as well as the (left length +1)*node value. In our example that is
(3+1)*(5+9) - (2*5+9) + 0 + (0+1)*4 = 3*9 + 2*5 + 4
and if the parent is on the left we switch left and right as appropriate.
value_sum = left_value_sum + right_value_sum + node.value length = right_length+left_length+1 if(node.index > tree[node.parent].index): value_sequence_sum = (length+1)*(left_value_sum) - left_value_sequence_sum + right_value_sequence_sum + (right_length+1)*node.value else: value_sequence_sum = (length+1)*(right_value_sum) - right_value_sequence_sum + left_value_sequence_sum + (left_length+1)*node.value return length, value_sum, value_sequence_sum, total_weird_sum
This part of the code does this and returns the new value sequence sum, the new value sum (4+5+9 in our case), and the length (3 in our case).
Constraintsalready, is that what you are asking?[3,3], min is 3 and total of items = 3part is my question.