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 Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)

import java.io.*;
import java.math.BigInteger;
import java.util.*;



public class Main {

    private static int[][] st;
    private static int [] logs;
    private static Set<List<Integer>> permutations;
    private static int index = 0;
    private static int max = 0;
    public static void main(String[] args) throws IOException {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        InputReader.OutputWriter out = new InputReader.OutputWriter(outputStream);
        Scanner scanner = new Scanner(System.in);


        int n = in.nextInt();
        int [] a = new int[n];
        for (int i = 0; i < a.length; i++) {
            a[i] = in.nextInt();
        }

        //out.println(canForm(218, 233, 704));
        shuffle(a);
        Arrays.sort(a);

        int count = 0;
        for (int i = 0; i < a.length; i++) {
            for (int j = i+1; j < a.length; j++) {
                int lower = lower(a,i,j);
                int higher = upper(a,i,j);
                //out.println(a[i] + " " + a[j] +" " + lower + " " + higher);
                if(lower!=-1) {
                    count+=(higher-lower + 1);
                }
            }
        }
        out.println(count);
        out.flush();
    }
    private static int lower(int [] a, int i, int j) {
        int lo = j + 1;
        int hi = a.length - 1;
        int ans = -1;
        while (lo<=hi) {
            int med = lo + (hi-lo)/2;
            if(canForm(a[i],a[j],a[med])) {
                ans = lo;
                hi = med - 1;
            }
            else {
                hi = med - 1;
            }
        }
        return ans;
    }
    private static int upper(int [] a, int i, int j) {
        int lo = j + 1;
        int hi = a.length - 1;
        int ans = -1;
        while (lo<=hi) {
            int med = lo + (hi-lo)/2;
            if(canForm(a[i],a[j],a[med])) {
                ans = lo;
                lo = med + 1;
            }
            else {
                hi = med - 1;
            }
        }
        return ans;
    }
    private static boolean canForm(int a, int b, int c) {
        return a < b + c && b < a + c && c < a + b;
    }
    private static void reverse(char [] c, int i, int j) {
        while (i < j) {
            char temp = c[i];
            c[i] = c[j];
            c[j] = temp;
            i++;
            j--;
        }
    }
    private static void shuffle(int [] a) {
        for (int i = 0; i < a.length; i++) {
            int index = (int)(Math.random()*(i+1));
            int temp = a[i];
            a[i] = a[index];
            a[index] = temp;
        }
    }
    private static int sumOfDigits(int n) {
        int sum = 0;
        while (n > 0) {
            sum+=n%10;
            n/=10;
        }
        return sum;
    }
    private static String reverse(char [] c) {
        int i = 0;
        int j = c.length - 1;
        while (i <= j) {
            char temp = c[i];
            c[i] = c[j];
            c[j] = temp;
            i++;
            j--;
        }
        return new String(c);
    }
    private static boolean isPalindrome (StringBuilder sb) {
        int i = 0;
        int j = sb.length() - 1;
        while (i <= j) {
            if(sb.charAt(i++) != sb.charAt(j--)) {
                return false;
            }
        }
        return true;
    }
    private static boolean isPalindrome(String s) {
        int i = 0;
        int j = s.length() - 1;
        while (i < j) {
            if(s.charAt(i) != s.charAt(j)) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }
    private static void outputQueue(Map<String,LinkedList<String>> map, String faculty, InputReader.OutputWriter out) {
        out.println(faculty+":");
        LinkedList<String> q = map.get(faculty);
        while (!q.isEmpty()) {
            out.println(q.pollFirst());
        }
        out.println();
    }

    public static long gcd(long a, long b) {
       while (b > 0) {
           long temp = a;
           a = b;
           b = temp%b;
       }
       return a;
    }


    private static int factorization(long n) {
        Set<Long> set = new HashSet<>();
        for(long i = 2; i * i <=n; i++) {
            while (n % i == 0) {
                set.add(i);
                n /= i;
            }
        }
        if(n > 1) set.add(n);
        return set.size();
    }

    private static void permute(int [] a, int l, int r) {
        if(l == r) {
            List<Integer> list = new ArrayList<>();
            for(int i : a) list.add(i);
            permutations.add(list);
        }
        else {
            for (int i = l; i <=r; i++) {
                swap(a,l,i);
                permute(a,l+1,r);
                swap(a,l,i);
            }
        }
    }
    private static void swap(int [] a, int l, int r) {
        int temp = a[l];
        a[l] = a[r];
        a[r] = temp;
    }

}

class InputReader extends BufferedReader {
    StringTokenizer tokenizer;

    public InputReader(InputStream inputStream) {
        super(new InputStreamReader(inputStream), 32768);
    }

    public InputReader(String filename) {
        super(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(filename)));
    }

    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(readLine());
            } catch (IOException e) {
                throw new RuntimeException();
            }
        }
        return tokenizer.nextToken();
    }

    public Integer nextInt(){
        return Integer.valueOf(next());
    }
    public Long nextLong() {
        return  Long.valueOf(next());
    }
    public Double nextDouble() {
        return Double.valueOf(next());
    }
    static class OutputWriter extends PrintWriter {
        public OutputWriter(OutputStream outputStream) {
            super(outputStream);
        }

        public OutputWriter(Writer writer) {
            super(writer);
        }

        public OutputWriter(String filename) throws FileNotFoundException {
            super(filename);
        }

        public void close() {
            super.close();
        }
    }
}