This problem is same as the previous one, but has larger constraints.

Shiro's just moved to the new house. She wants to invite all friends of her to the house so they can play monopoly. However, her house is too small, so she can only invite one friend at a time.

For each of the n days since the day Shiro moved to the new house, there will be exactly one cat coming to the Shiro's house. The cat coming in the i-th day has a ribbon with color u_i. Shiro wants to know the largest number x, such that if we consider the streak of the first x days, it is possible to remove exactly one day from this streak so that every ribbon color that has appeared among the remaining x - 1 will have the same number of occurrences.

For example, consider the following sequence of u_i: [2, 2, 1, 1, 5, 4, 4, 5]. Then x = 7 makes a streak, since if we remove the leftmost u_i = 5, each ribbon color will appear exactly twice in the prefix of x - 1 days. Note that x = 8 doesn't form a streak, since you must remove exactly one day. 

Since Shiro is just a cat, she is not very good at counting and needs your help finding the longest streak.

Input

The first line contains a single integer n (1 ≤ n ≤ 10^5) — the total number of days.

The second line contains n integers u_1, u_2, …, u_n (1 ≤ u_i ≤ 10^5) — the colors of the ribbons the cats wear. 

Output

Print a single integer x — the largest possible streak of days.

Examples

Input


13
1 1 1 2 2 2 3 3 3 4 4 4 5


Output


13

Input


5
10 100 20 200 1


Output


5

Input


1
100000


Output


1

Input


7
3 2 1 1 4 5 1


Output


6

Input


6
1 1 1 2 2 2


Output


5

Note

In the first example, we can choose the longest streak of 13 days, since upon removing the last day out of the streak, all of the remaining colors 1, 2, 3, and 4 will have the same number of occurrences of 3. Note that the streak can also be 10 days (by removing the 10-th day from this streak) but we are interested in the longest streak.

In the fourth example, if we take the streak of the first 6 days, we can remove the third day from this streak then all of the remaining colors 1, 2, 3, 4 and 5 will occur exactly once.
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.util.InputMismatchException;
import java.util.HashMap;
import java.io.IOException;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.Map;
import java.util.SortedMap;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastReader in = new FastReader(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        B1CatPartyEasyEdition solver = new B1CatPartyEasyEdition();
        solver.solve(1, in, out);
        out.close();
    }

    static class B1CatPartyEasyEdition {
        public void solve(int testNumber, FastReader in, PrintWriter out) {
            Debug debug = new Debug();
            int n = in.nextInt();
            int[] a = in.nextIntArray(n);

            TreeMultiSet<Integer> set = new TreeMultiSet<>(new TreeMap<>());
            Counter<Integer> counter = new Counter<>();

            int ans = 0;
            for (int i = 0; i < n; ++i) {
                int cur = a[i];

                int count = counter.getCount(cur);
                set.remove(count);
                counter.add(cur);
                ++count;
                set.add(count);
//            debug.tr(cur, count, set.getDistinctCount());
                if (set.getDistinctCount() == 1) {
                    if (i + 1 < n) ans = i + 1;
                    else if (set.minValue() == 1) ans = i;
                } else if (set.getDistinctCount() == 2) {
                    int v1 = set.minValue();
                    int v2 = set.maxValue();
                    int c1 = set.getCount(v1);
                    int c2 = set.getCount(v2);
                    if (v1 == 1 && c1 == 1) ans = i;
                    else if (c2 == 1 && v2 - v1 == 1) ans = i;
                }
            }
            out.println(ans + 1);
        }

    }

    static class Counter<K> {
        Map<K, Integer> map;

        public Counter() {
            map = new HashMap<>();
        }

        public void add(K key) {
            Integer count = map.get(key);
            if (count == null) count = 0;
            ++count;
            map.put(key, count);
        }

        public Integer getCount(K key) {
            Integer count = map.get(key);
            return count == null ? 0 : count;
        }

    }

    static abstract class MultiSetImpl<ValueType, MapType extends Map<ValueType, Integer>> implements MultiSet<ValueType> {
        protected final MapType map;
        protected int size;
        protected int distinctCount;

        protected MultiSetImpl(MapType map) {
            this.map = map;
            this.size = 0;
        }

        public void add(ValueType value) {
            int count = getCount(value);
            if (count == 0) ++distinctCount;
            map.put(value, count + 1);
            ++size;
        }

        public boolean remove(ValueType value) {
            int count = getCount(value);
            if (count == 0) return false;

            if (count == 1) map.remove(value);
            else map.put(value, count - 1);
            if (count == 1) --distinctCount;
            --size;
            return true;
        }

        public int getCount(ValueType value) {
            Integer count = map.get(value);
            return (count == null ? 0 : count);
        }

        public String toString() {
            StringBuilder stringBuilder = new StringBuilder();
            for (ValueType key : map.keySet()) {
                stringBuilder.append("[" + key.toString() + " " + map.get(key).toString() + "] ");
            }
            return stringBuilder.toString();
        }

        public int getDistinctCount() {
            return distinctCount;
        }

    }

    static interface SortedMultiSet<ValueType> extends MultiSet<ValueType> {
    }

    static abstract class SortedMultiSetImpl<ValueType> extends MultiSetImpl<ValueType, NavigableMap<ValueType, Integer>> implements SortedMultiSet<ValueType> {
        public SortedMultiSetImpl(NavigableMap<ValueType, Integer> map) {
            super(map);
        }

        public ValueType minValue() {
            return (size == 0 ? null : map.firstKey());
        }

        public ValueType maxValue() {
            return (size == 0 ? null : map.lastKey());
        }

    }

    static class Debug {
        PrintWriter out;
        boolean oj;
        long timeBegin;
        Runtime runtime;

        public Debug(PrintWriter out) {
            oj = System.getProperty("ONLINE_JUDGE") != null;
            this.out = out;
            this.timeBegin = System.currentTimeMillis();
            this.runtime = Runtime.getRuntime();
        }

        public Debug() {
            oj = System.getProperty("ONLINE_JUDGE") != null;
            OutputStream outputStream = System.err;
            this.out = new PrintWriter(outputStream);
            this.timeBegin = System.currentTimeMillis();
            this.runtime = Runtime.getRuntime();
        }

        public void finalize() {
            out.flush();
            out.close();
        }

    }

    static class TreeMultiSet<ValueType> extends SortedMultiSetImpl<ValueType> {
        public TreeMultiSet(NavigableMap<ValueType, Integer> map) {
            super(map);
        }

    }

    static class FastReader {
        private InputStream stream;
        private byte[] buf = new byte[8192];
        private int curChar;
        private int pnumChars;

        public FastReader(InputStream stream) {
            this.stream = stream;
        }

        private int pread() {
            if (pnumChars == -1) {
                throw new InputMismatchException();
            }
            if (curChar >= pnumChars) {
                curChar = 0;
                try {
                    pnumChars = stream.read(buf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (pnumChars <= 0) {
                    return -1;
                }
            }
            return buf[curChar++];
        }

        public int nextInt() {
            int c = pread();
            while (isSpaceChar(c))
                c = pread();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = pread();
            }
            int res = 0;
            do {
                if (c == ',') {
                    c = pread();
                }
                if (c < '0' || c > '9') {
                    throw new InputMismatchException();
                }
                res *= 10;
                res += c - '0';
                c = pread();
            } while (!isSpaceChar(c));
            return res * sgn;
        }

        public int[] nextIntArray(int n) {
            int[] array = new int[n];
            for (int i = 0; i < n; i++) {
                array[i] = nextInt();
            }
            return array;
        }

        private boolean isSpaceChar(int c) {
            return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
        }

    }

    static interface MultiSet<ValueType> {
    }
}

