Problem:
Score : 700 points

Problem Statement

N problems are proposed for an upcoming contest. Problem i has an initial integer score of A_i points.

M judges are about to vote for problems they like. Each judge will choose exactly V problems, independently from the other judges,
and increase the score of each chosen problem by 1.

After all M judges cast their vote, the problems will be sorted in non-increasing order of score, and the first P problems will be chosen for the problemset.
Problems with the same score can be ordered arbitrarily, this order is decided by the chief judge.

How many problems out of the given N have a chance to be chosen for the problemset?

Constraints

2 \le N \le 10^5

1 \le M \le 10^9

1 \le V \le N - 1

1 \le P \le N - 1

0 \le A_i \le 10^9

Input

Input is given from Standard Input in the following format:

N M V P
A_1 A_2 ... A_N

Output

Print the number of problems that have a chance to be chosen for the problemset.

Sample Input 1

6 1 2 2
2 1 1 3 0 2

Sample Output 1

5

If the only judge votes for problems 2 and 5, the scores will be 2 2 1 3 1 2.
The problemset will consist of problem 4 and one of problems 1, 2, or 6.

If the only judge votes for problems 3 and 4, the scores will be 2 1 2 4 0 2.
The problemset will consist of problem 4 and one of problems 1, 3, or 6.

Thus, problems 1, 2, 3, 4, and 6 have a chance to be chosen for the problemset. On the contrary, there is no way for problem 5 to be chosen.

Sample Input 2

6 1 5 2
2 1 1 3 0 2

Sample Output 2

3

Only problems 1, 4, and 6 have a chance to be chosen.

Sample Input 3

10 4 8 5
7 2 3 6 1 6 5 4 6 5

Sample Output 3

8

Solution in C# (Mono 4.6.2.0) (judge verdict: Runtime Error)

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

namespace AtCoder
{
    class Program
    {
        static void Main(string[] args)
        {
            input_iter = LazyLoadAllLines();
            //------------------------------------------------//
            var n = Read<long>();
            var m = Read<long>();
            var v = Read<long>();
            var p = Read<long>();
            //var s = Read();
            /*List<string> sls = new List<string>();
            for(int i = 0; i < h; ++i)
            {
                sls.Add(Read());
            }*/
            var als = Read<long>(n);
            //var bls = Read<long>(n);
            /*List<List<long>> abls = new List<List<long>>();
            for (int i = 0; i < n - 1; ++i)
            {
                var x = Read<long>(2);
                if (x[0] > x[1]) x.Reverse();
                abls.Add(x);
            }*/
            //List<List<long>> abls = new List<List<long>>();
            //List<long> cls = new List<long>();
            /*List<long> edgeNum = Enumerable.Repeat(0L, (int)n).ToList();
            for (int i = 0; i < n - 1; ++i)
            {
                abls.Add(Read<long>(2));
                abls[i].Add(i);
                abls[i].Add(-1);
                --abls[i][0];
                --abls[i][1];
                //cls.Add(Read<long>());
                ++edgeNum[(int)abls[i][0]];
                ++edgeNum[(int)abls[i][1]];
            }*/

            als.Sort((l, r) => (int)(r - l));

            var minimum = als[(int)p - 1];
            var minNum = als.Where(val => val == minimum).Count();
            //var alwaysTakenNum = als.Where(val => val > minimum).Count();
            var takeNum = p - als.Where(val => val > minimum).Count();

            var leftNum = minNum - takeNum;
            //var cnt = p;


            // 3 3 3 2 2 | 2 2 2 1 1 0 ->
            // 3 2 2 | 2 2 1 1 0
            // 7 6 6 6 5 | 5 4 3 2 1

            List<long[]> ls = new List<long[]>();
            var prev = als[(int)(p + leftNum)];
            var cnt = 0L;
            for(int i = (int)(p + leftNum); i < n; ++i)
            {
                if(prev != als[i])
                {
                    ls.Add(new long[] { prev, cnt });
                    prev = als[i];
                    cnt = 0;
                }
                ++cnt;
            }
            ls.Add(new long[] { prev, cnt });


            cnt = p + leftNum;
            if (cnt == n)
            {
                Console.WriteLine(cnt);
                return;
            }
            long lockNum = minNum;
            long lockTotal = lockNum * minimum;
            foreach (var val in ls)
            {
                if (v > n - lockNum)
                {
                    var added = lockTotal + m * (v - (n - lockNum));
                    var num = added / lockNum;
                    var overNum = added % lockNum;

                    if (!(num + 1 <= val[0] + m || ((num == val[0] + m) && overNum < takeNum))) break;
                }
                if (val[0] + m < minimum) break;
                cnt += val[1];

                lockNum += val[1];
                lockTotal += val[0] * val[1];
            }
            Console.WriteLine(cnt);
        }

        static IEnumerator<string> input_iter;

        static IEnumerator<string> LazyLoadAllLines()
        {
            string line;
            do
            {
                line = Console.ReadLine();
                foreach (var s in line.Split(' '))
                    yield return s;
            } while (line != null);
        }
        static _T Read<_T>() where _T : struct
        {
            input_iter.MoveNext();
            return (_T)Convert.ChangeType(input_iter.Current, typeof(_T));
        }
        static string Read()
        {
            input_iter.MoveNext();
            return input_iter.Current;
        }
        static List<_T> Read<_T>(long num) where _T : struct {
            List<_T> res = new List<_T>();
            for (long i = 0; i < num; ++i)
            {
                input_iter.MoveNext();
                res.Add((_T)Convert.ChangeType(input_iter.Current, typeof(_T)));
            }
            return res;
        }
        

        public class PriorityQueue<T> where T : IComparable
        {
            private IComparer<T> comparer = null;
            private bool isAccendingOrder;

            private List<T> heap;
            private int heapCurrentSize = 0;

            public PriorityQueue(IComparer<T> comparer, int initialHeapSize = 256)
            {
                heap = new List<T>(initialHeapSize);
                this.comparer = comparer;
            }

            public PriorityQueue(bool isAccending = true, int initialHeapSize = 256)
            {
                heap = new List<T>(initialHeapSize);
                isAccendingOrder = isAccending;
            }

            private int Compare(T x, T y)
            {
                if (comparer != null) return comparer.Compare(x, y);
                return isAccendingOrder ? x.CompareTo(y) : y.CompareTo(x);
            }

            public bool Empty()
            {
                return Count() == 0;
            }

            public int Count()
            {
                return heapCurrentSize;
            }

            public void Push(T x)
            {
                //node number
                var idx = heapCurrentSize++;
                if (heapCurrentSize > heap.Count) heap.Capacity *= 2;

                while (idx > 0)
                {
                    //parent node number
                    var parentIdx = (idx - 1) / 2;

                    if (Compare(heap[parentIdx], x) <= 0) break;

                    heap[idx] = heap[parentIdx];
                    idx = parentIdx;
                }

                heap[idx] = x;
            }

            public T Pop()
            {
                T ret = heap[0];
                T x = heap[--heapCurrentSize];

                int idx = 0;
                while (idx * 2 + 1 < heapCurrentSize)
                {
                    //children
                    int a = idx * 2 + 1;
                    int b = idx * 2 + 2;

                    if (b < heapCurrentSize && Compare(heap[b], heap[a]) < 0) a = b;

                    if (Compare(heap[a], x) >= 0) break;

                    heap[idx] = heap[a];
                    idx = a;
                }

                heap[idx] = x;

                return ret;
            }

            public T Peek()
            {
                return heap[0];
            }

            public bool Contains(T x)
            {
                for (int i = 0; i < heapCurrentSize; i++) if (x.Equals(heap[i])) return true;
                return false;
            }

            public void Clear()
            {
                while (heapCurrentSize > 0) Pop();
            }

            public IEnumerator<T> GetEnumerator()
            {
                var temp = new List<T>();

                while (heapCurrentSize > 0)
                {
                    temp.Add(Pop());
                }

                foreach (var value in temp)
                {
                    Push(value);
                    yield return value;
                }
            }

            public T[] ToArray()
            {
                T[] array = new T[heapCurrentSize];
                int i = 0;

                foreach (var r in this)
                {
                    array[i] = r;
                    ++i;
                }

                return array;
            }
        }
    }
}