Problem:
Score : 300 points

Problem Statement

There are N observatories in AtCoder Hill, called Obs. 1, Obs. 2, ..., Obs. N. The elevation of Obs. i is H_i.
There are also M roads, each connecting two different observatories. Road j connects Obs. A_j and Obs. B_j.

Obs. i is said to be good when its elevation is higher than those of all observatories that can be reached from Obs. i using just one road.
Note that Obs. i is also good when no observatory can be reached from Obs. i using just one road.

How many good observatories are there?

Constraints

2 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq H_i \leq 10^9

1 \leq A_i,B_i \leq N

A_i \neq B_i

Multiple roads may connect the same pair of observatories.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M
H_1 H_2 ... H_N
A_1 B_1
A_2 B_2
:
A_M B_M

Output

Print the number of good observatories.

Sample Input 1

4 3
1 2 3 4
1 3
2 3
2 4

Sample Output 1

2

From Obs. 1, you can reach Obs. 3 using just one road. The elevation of Obs. 1 is not higher than that of Obs. 3, so Obs. 1 is not good.

From Obs. 2, you can reach Obs. 3 and 4 using just one road. The elevation of Obs. 2 is not higher than that of Obs. 3, so Obs. 2 is not good.

From Obs. 3, you can reach Obs. 1 and 2 using just one road. The elevation of Obs. 3 is higher than those of Obs. 1 and 2, so Obs. 3 is good.

From Obs. 4, you can reach Obs. 2 using just one road. The elevation of Obs. 4 is higher than that of Obs. 2, so Obs. 4 is good.

Thus, the good observatories are Obs. 3 and 4, so there are two good observatories.

Sample Input 2

6 5
8 6 9 1 2 1
1 3
4 2
4 3
4 6
4 6

Sample Output 2

3

Solution in C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;

public class ABC166_C
{

    public static void Main()
    {
        InLine(out int n, out int k);
        InLineArg(out int[] hei);
        bool[] bs = new bool[n];
        for(int i = 0;i < k; i++)
        {
            InLine(out int a, out int b);
            if (hei[a - 1] >= hei[b - 1]) bs[b - 1] = true;
            if (hei[a - 1] <= hei[b - 1]) bs[a - 1] = true;
        }

        foreach (var b in bs) if (b == false) result++; 
        Out(result);
    }

    /* Template */
    private static object[] nullobj = null;
    public static int len = -1;
    public static int count = -1;
    public static double result = 0;
    public static string line = "";

    //文字コード変換
    public static int ConvertInt(char c)
    {
        return c;
    }

    //配列入力:1入力
    public static A[] InArgs<A>(int count)
    {
        InArgs(count, out A[] var, out nullobj, out nullobj, 1);
        return var;
    }

    //配列入力:1入力
    public static void InArgs<A>(int count, out A[] var)
    {
        InArgs(count, out var, out nullobj, out nullobj, 1);
    }

    //配列入力:2入力
    public static void InArgs<A, B>(int count, out A[] var1, out B[] var2)
    {
        InArgs(count, out var1, out var2, out nullobj, 2);
    }

    //配列入力:3入力
    public static void InArgs<A, B, C>(int count, out A[] var1, out B[] var2, out C[] var3)
    {
        InArgs(count, out var1, out var2, out var3, 3);
    }

    //配列入力:内部処理
    private static void InArgs<A, B, C>(int count, out A[] var1, out B[] var2, out C[] var3, int ci)
    {
        var1 = new A[count];
        var2 = new B[count];
        var3 = new C[count];
        for (int i = 0; i < count; i++)
        {
            InLine(out var1[i], out var2[i], out var3[i], ci);
        }
    }

    //入力:1入力
    public static A InLine<A>()
    {
        InLine(out A var);
        return var;
    }

    //入力:1入力
    public static void InLine<A>(out A var)
    {
        InLine(out var, out nullobj, out nullobj, 1);
    }

    //入力:2入力
    public static void InLine<A, B>(out A var1, out B var2)
    {
        InLine(out var1, out var2, out nullobj, 2);
    }

    //入力:3入力
    public static void InLine<A, B, C>(out A var1, out B var2, out C var3)
    {
        InLine(out var1, out var2, out var3, 3);
    }

    //入力:内部処理
    public static void InLine<A, B, C>(out A var1, out B var2, out C var3, int c)
    {
        var2 = default;
        var3 = default;
        object[] o = new object[c];
        Type[] t = new Type[] { typeof(A), typeof(B), typeof(C) };

        var line = Console.ReadLine();
        string[] s;
        if (o.Length == 1) s = new string[1] { line };
        else s = line.Split(' ');
        for (int i = 0; i < s.Length; i++)
        {
            if (typeof(int) == t[i]) o[i] = int.Parse(s[i]);
            else if (typeof(long) == t[i]) o[i] = long.Parse(s[i]);
            else if (typeof(double) == t[i]) o[i] = double.Parse(s[i]);
            else o[i] = s[i];
        }
        var1 = (A)o[0];
        if (c == 2) var2 = (B)o[1];
        if (c == 3) var3 = (C)o[2];
    }

    //入力:1行配列
    public static A[] InLineArg<A>()
    {
        InLineArg(out A[] var);
        return var;
    }

    //入力:1行配列
    public static void InLineArg<A>(out A[] arg)
    {
        object obj = null;
        Type t = typeof(A);
        string[] line = Console.ReadLine().Split(' ');
        if (typeof(int) == t) obj = line.Select(int.Parse).ToArray();
        else if (typeof(long) == t) obj = line.Select(long.Parse).ToArray();
        else if (typeof(double) == t) obj = line.Select(double.Parse).ToArray();
        else obj = line;
        arg = (A[])obj;
    }

    //文字列結合
    public static string JoinString(object obj, string sep)
    {
        return obj.GetType().IsArray ?
            string.Join(sep, ((IEnumerable<object>)obj).Select(i => i.ToString()).ToArray()) : obj.ToString();
    }

    //出力
    public static void Out(object o)
    {
        Console.WriteLine(o);
    }

    //出力:変数result
    public static void OutResult()
    {
        Console.WriteLine(result);
    }

    //出力:Yes
    public static void OutYes()
    {
        Console.WriteLine("Yes");
    }

    //出力:No
    public static void OutNo()
    {
        Console.WriteLine("No");
    }

    //出力:YES
    public static void OutYES()
    {
        Console.WriteLine("YES");
    }

    //出力:NO
    public static void OutNO()
    {
        Console.WriteLine("NO");
    }

    //辞書生成
    private static Dictionary<A, B> PutDict<A, B>(A[] key, B[] value)
    {
        if (key.Length != value.Length) return null;
        var dic = new Dictionary<A, B>();
        for (int i = 0; i < Math.Min(key.Length, value.Length); i++)
        {
            if (!dic.ContainsKey(key[i])) dic.Add(key[i], value[i]);
            else dic[key[i]] = value[i];
        }
        return dic;
    }

    //最大
    public static int[] Max(int[] array, int count)
    {
        int[] result = new int[count];
        for (int c = 0; c < count; c++)
        {
            int max = -1;
            int plus = Vector<int>.Count;
            var vmax = new Vector<int>(max);
            for (int i = 0; i < array.Length - plus; i += plus)
            {
                vmax = Vector.Max(vmax, new Vector<int>(array, i));
            }
            for (int i = 0; i < plus; i++)
            {
                if (max < vmax[i]) max = vmax[i];
            }
            for (int i = array.Length - plus; i < array.Length; i++)
            {
                if (i < 0) i = 0;
                if (max < array[i]) max = array[i];
            }

            result[c] = max;
            if (c != count - 1)
            {
                var list = new List<int>(array);
                list.Remove(max);
                array = list.ToArray();
            }
        }
        return result;
    }

    //最小
    public static int[] Min(int[] array, int count)
    {
        int[] result = new int[count];
        for (int c = 0; c < count; c++)
        {
            int min = int.MaxValue;
            int plus = Vector<int>.Count;
            var vmax = new Vector<int>(min);
            for (int i = 0; i < array.Length - plus; i += plus)
            {
                vmax = Vector.Min(vmax, new Vector<int>(array, i));
            }
            for (int i = 0; i < plus; i++)
            {
                if (min > vmax[i]) min = vmax[i];
            }
            for (int i = array.Length - plus; i < array.Length; i++)
            {
                if (i < 0) i = 0;
                if (min > array[i]) min = array[i];
            }

            result[c] = min;
            if (c != count - 1)
            {
                var list = new List<int>(array);
                list.Remove(min);
                array = list.ToArray();
            }
        }
        return result;
    }

    //公約数
    public static int[] CommonDivisor(int num)
    {
        return CommonDivisor((double)num).Select(i => (int)i).ToArray();
    }

    public static double[] CommonDivisor(double num)
    {
        double l = 2, n = num;
        double[] result = new double[0];

        while (l * l <= num)
        {
            if (n % l == 0)
            {
                n /= l;
                Array.Resize(ref result, result.Length + 1);
                result[^1] = l;
            }
            else l++;
        }
        if (n != 1)
        {
            Array.Resize(ref result, result.Length + 1);
            result[^1] = n;
        }
        return result;
    }

    //大小比較
    public static bool Compare(bool lequal, double a, double x, double b, bool requal)
    {
        if (a <= x && x <= b)
        {
            if ((!lequal && x == a) || (!requal && x == b)) return false;
            else return true;
        }
        return false;
    }

    //互いに素
    public static bool IsRelativelyPrime(double a, double b)
    {
        return a > 1 && b > 1 ? CommonDivisor(a).Intersect(CommonDivisor(b)).ToArray().Length == 0 : false;
    }

    //素数判定
    public static bool IsPrimeNumber(int num)
    {
        if (num < 2) return false;
        else if (num == 2) return true;
        else if (num % 2 == 0) return false;

        double sqrtNum = Math.Sqrt(num);
        for (int i = 3; i <= sqrtNum; i += 2)
        {
            if (num % i == 0) return false;
        }
        return true;
    }

    //最大公約数
    public static int GCD(int a, int b)
    {
        return (int)GCD((double)a, b);
    }

    public static double GCD(double a, double b)
    {
        double[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        Dictionary<double, int> dic1 = new Dictionary<double, int>(), dic2 = new Dictionary<double, int>();
        int count = 0;
        double n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic1.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic1.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
        foreach (double l in dic2.Keys)
        {
            result *= Math.Pow(l, dic2[l]);
        }
        return result;
    }

    //最小公倍数
    public static double LCM(double a, double b)
    {
        double[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        var dic = new Dictionary<double, int>();
        int count = 0;
        double n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
                else if (n != 0) dic.Add(n, count);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
        else dic.Add(n, count);
        foreach (double l in dic.Keys)
            result *= (double)Math.Pow(l, dic[l]);
        return result;
    }

    //組合せ数(nCr)
    public static double Combination(int n, int r)
    {
        if (n / 2 < r) r = n - r;
        return TotalPower(n, r + 1) / TotalPower(n - r);
    }

    //組合せ数総和(Σ(k=1,n,nCk))
    public static double CombinationSum(int n)
    {
        return Math.Pow(2, n);
    }

    //重複組合せ数(nHr)
    public static double RepetitionCombination(int n, int r)
    {
        return Combination(n + r - 1, r);
    }

    //重複組合せ数総和(Σ(k=1,n,nHk))
    public static double RepetitionCombinationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionCombination(n, i);
        }
        return result;
    }

    //順列数(nPr)
    public static double Permutation(int n, int r)
    {
        return TotalPower(n, r + 1);
    }

    //順列数総和(Σ(k=1,n,nPk))
    public static double PermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += Permutation(n, i);
        }
        return result;
    }

    //円順列数
    public static double CircularPermutation(int n)
    {
        return TotalPower(n - 1);
    }

    //円順列数総和
    public static double CircularPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += CircularPermutation(i);
        }
        return result;
    }



    //数珠順列数
    public static double NecklacePermutation(int n)
    {
        return CircularPermutation(n - 1) / 2;
    }

    //数珠順列数総和
    public static double NecklacePermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += NecklacePermutation(i);
        }
        return result;
    }

    //重複順列数(nΠr)
    public static double RepetitionPermutation(int n, int r)
    {
        return Math.Pow(n, r);
    }

    //重複順列数総和(Σ(k=1,n,nΠk))
    public static double RepetitionPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionPermutation(n, i);
        }
        return result;
    }

    //総乗
    public static double TotalPower(int max)
    {
        return TotalPower(max, 1);
    }

    public static double TotalPower(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result *= i;
        return result;
    }

    public static double TotalPower(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result *= i;
        return result;
    }

    //総和
    public static double TotalSum(int max)
    {
        return TotalSum(max, 1);
    }

    public static double TotalSum(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result += i;
        return result;
    }

    public static double TotalSum(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result += i;
        return result;
    }
}