Section OneStep.
Variable A : Type.
Variable f : A -> nat.
(* A step is valid if the two smallest elements of the initial list have been merged *)
Definition one_step (l1 l2 : list (btree A)) : Prop :=
exists l3 : list (btree A),
(exists t1 : btree A,
(exists t2 : btree A,
ordered (sum_order f) (t1 :: t2 :: l3) /\
permutation l1 (t1 :: t2 :: l3) /\
permutation l2 (node t1 t2 :: l3))).
Proof using.
intros l1 l2 l3 (l4, (t1, (t2, (H1, (H2, H3)))))
(l5, (t3, (t4, (H4, (H5, H6))))).
rewrite weight_tree_list_permutation with (1 := H3).
rewrite weight_tree_list_permutation with (1 := H6).
repeat rewrite weight_tree_list_node.
apply f_equal2 with (f := plus).
cut
(map (sum_leaves f) (t1 :: t2 :: l4) = map (sum_leaves f) (t3 :: t4 :: l5)).
simpl in |- *; intros H7; injection H7.
intros H8 H9 H10; repeat apply f_equal2 with (f := plus); auto.
apply ordered_sum_leaves_eq; auto.
apply permutation_trans with (2 := H5); auto.
apply permutation_sym; auto.
rewrite <- weight_tree_list_permutation with (1 := H2).
apply weight_tree_list_permutation; auto.
Qed.

(* Choosing one step or another does not change the sum of leaves *)
Theorem one_step_same_sum_leaves :
forall l1 l2 l3 : list (btree A),
one_step l1 l2 -> one_step l1 l3 -> same_sum_leaves f l2 l3.