Section section_for_maxs.
#[local] Notation In := List.In.
Definition maxs : list nat -> nat := fold_right max 0.
Proof with (lia || eauto).
unfold maxs. revert n H_IN. induction ns as [ | n' ns IH]; simpl...
intros n [H_eq | H_in]... enough (ENOUGH: fold_right max 0 ns >= n)...
Qed.
Proof with (lia || eauto).
unfold maxs. revert ns2.
induction ns1 as [ | n1 ns1 IH]; simpl...
intros n; rewrite IH...
Qed.
Proof with try now (lia || firstorder; eauto).
unfold maxs. induction ns as [ | n1 ns1 IH]; simpl... intros n phi_n.
destruct (le_gt_dec n n1) as [H_le | H_gt]... enough (claim1 : fold_right max 0 ns1 >= n)...
destruct (phi_dec n) as [H_yes | H_no]... destruct (phi_in n H_yes)...
enough (claim2 : forall ks : list nat, forall k : nat, In k ks -> fold_right max 0 ks >= k)...
induction ks; simpl... intros k [H_eq | H_in]... enough (claim3: fold_right Init.Nat.max 0 ks >= k)...
Qed.
Proof with try now (lia || firstorder; eauto).
unfold maxs. induction ns as [ | n1 ns1 IH]; simpl... intros n.
destruct (le_gt_dec n1 (fold_right Init.Nat.max 0 ns1)); split.
- intros H_gt. assert (claim1: fold_right Init.Nat.max 0 ns1 > n)...
- intros [i [[H_eq | H_in] H_gt]]... enough (claim2: fold_right max 0 ns1 > n)...
- intros H_gt. exists n1...
- intros [i [[H_eq | H_in] H_gt]]... enough (claim3: fold_right Init.Nat.max 0 ns1 > n)...
Qed.
Proof with try now (lia || firstorder; eauto).
unfold maxs. revert ns2 H_SUBSET; induction ns1 as [ | n1 ns1 IH]; simpl...
intros ns2 H. destruct (le_gt_dec n1 (fold_right max 0 ns1)).
- enough (ENOUGH : fold_right max 0 ns1 <= fold_right max 0 ns2)...
- enough (ENOUGH : n1 <= fold_right max 0 ns2)... eapply in_maxs_ge...
Qed.
Proof with try now firstorder.
unfold maxs. enough (claim1 : fold_right max 0 ns1 <= fold_right max 0 ns2 /\ fold_right max 0 ns2 <= fold_right max 0 ns1) by lia.
split; eapply maxs_subset...
Qed.

Lemma maxs_sim ns1 ns2
(SIM : forall n, In n ns1 -> exists n', In n' ns2 /\ n <= n')
: maxs ns1 <= maxs ns2.