Problem:
Score : 400 points

Problem Statement

Takahashi has N sticks that are distinguishable from each other. The length of the i-th stick is L_i.

He is going to form a triangle using three of these sticks. Let a, b, and c be the lengths of the three sticks used. Here, all of the following conditions must be satisfied:

a < b + c

b < c + a

c < a + b

How many different triangles can be formed? Two triangles are considered different when there is a stick used in only one of them.

Constraints

All values in input are integers.

3 \leq N \leq 2 \times 10^3

1 \leq L_i \leq 10^3

Input

Input is given from Standard Input in the following format:

N
L_1 L_2 ... L_N

Constraints

Print the number of different triangles that can be formed.

Sample Input 1

4
3 4 2 1

Sample Output 1

1

Only one triangle can be formed: the triangle formed by the first, second, and third sticks.

Sample Input 2

3
1 1000 1

Sample Output 2

0

No triangles can be formed.

Sample Input 3

7
218 786 704 233 645 728 389

Sample Output 3

23

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace AtCoder
{
	public class ABC
	{
		static void Main(string[] args)
		{
			Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });


			int n = int.Parse(Console.ReadLine());
			int[] l = Console.ReadLine().Split().Select(int.Parse).OrderBy(p => p).ToArray();
			//System.Diagnostics.Debug.WriteLine(string.Join(" ", l));

			long ans = 0;
			for (int i = 0; i < n; i++) {
				for (int j = i + 1; j < n; j++) {
					int t = l[i] + l[j];
					int index = BinarySearch(l, j + 1, n - 1, t);
					if (index < 0) {
						index = ~index;
					}
					ans += index - (j + 1);
				}
			}
			Console.WriteLine(ans);


			Console.Out.Flush();
		}


		#region 二分探索 int BinarySearch<T>(T[] array, int lower, int upper, T value, Comparison<T> compare)
		public static int BinarySearch<T>(T[] array, T value) { return BinarySearch(array, 0, array.Length - 1, value, Comparer<T>.Default.Compare); }
		public static int BinarySearch<T>(T[] array, T value, IComparer<T> comparer) { return BinarySearch(array, 0, array.Length - 1, value, comparer.Compare); }
		public static int BinarySearch<T>(T[] array, T value, Func<T, T, int> compare) { return BinarySearch(array, 0, array.Length - 1, value, compare); }
		public static int BinarySearch<T>(T[] array, int lower, int upper, T value) { return BinarySearch(array, lower, upper, value, Comparer<T>.Default.Compare); }
		public static int BinarySearch<T>(T[] array, int lower, int upper, T value, IComparer<T> comparer) { return BinarySearch(array, lower, upper, value, comparer.Compare); }
		public static int BinarySearch<T>(T[] array, int lower, int upper, T value, Func<T, T, int> compare)
		{
			if (lower > upper) {
				return ~(upper + 1);
			}
			int up = upper, mid;
			while (lower < up) {
				mid = (lower + up) / 2;
				if (compare(array[mid], value) < 0) {
					lower = mid + 1;
				} else {
					up = mid;
				}
			}
			int r = compare(array[lower], value);
			if (r != 0) {
				if (lower == upper && r < 0) {
					lower++;
				}
				lower = ~lower;
			}
			return lower;
		}
		#endregion


	}
}