using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;

public static class Ex
{
    public static bool IsNullOrEmpty(this string s) { return string.IsNullOrEmpty(s); }
    public static void yesno(this bool b) => Console.WriteLine(b ? "yes" : "no");
    public static void YesNo(this bool b) => Console.WriteLine(b ? "Yes" : "No");
    public static void YESNO(this bool b) => Console.WriteLine(b ? "YES" : "NO");
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    //public static bool Chmax<T>(ref this T a, T b) where T : struct, IComparable<T>
    //{
    //    if (b.CompareTo(a) > 0) { a = b; return true; }
    //    else return false;
    //}
    //[MethodImpl(MethodImplOptions.AggressiveInlining)]
    //public static bool Chmin<T>(ref this T a, T b) where T : struct, IComparable<T>
    //{
    //    if (b.CompareTo(a) < 0) { a = b; return true; }
    //    else return false;
    //}

    public static List<string> FastSort(this List<string> s) { s.Sort(StringComparer.OrdinalIgnoreCase); return s.ToList(); }

    public static int PopCount(this uint bits)
    {
        bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
        bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
        bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
        bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
        return (int)((bits & 0x0000ffff) + (bits >> 16 & 0x0000ffff));
    }
}

partial class Program
{
    string GetStr() { return Console.ReadLine().Trim(); }
    char GetChar() { return Console.ReadLine().Trim()[0]; }
    int GetInt() { return int.Parse(Console.ReadLine().Trim()); }
    long GetLong() { return long.Parse(Console.ReadLine().Trim()); }
    double GetDouble() { return double.Parse(Console.ReadLine().Trim()); }
    string[] GetStrArray() { return Console.ReadLine().Trim().Split(' '); }
    string[][] GetStrArray(int N)
    {
        var res = new string[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ');
        return res;
    }
    int[] GetIntArray() { return Console.ReadLine().Trim().Split(' ').Select(int.Parse).ToArray(); }
    int[][] GetIntArray(int N)
    {
        var res = new int[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(int.Parse).ToArray();
        return res;
    }
    public long[] GetLongArray() { return Console.ReadLine().Trim().Split(' ').Select(long.Parse).ToArray(); }
    long[][] GetLongArray(int N)
    {
        var res = new long[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(long.Parse).ToArray();
        return res;
    }
    char[] GetCharArray() { return Console.ReadLine().Trim().Split(' ').Select(char.Parse).ToArray(); }
    double[] GetDoubleArray() { return Console.ReadLine().Trim().Split(' ').Select(double.Parse).ToArray(); }
    double[][] GetDoubleArray(int N)
    {
        var res = new double[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(double.Parse).ToArray();
        return res;
    }
    char[][] GetGrid(int H)
    {
        var res = new char[H][];
        for (int i = 0; i < H; i++) res[i] = Console.ReadLine().Trim().ToCharArray();
        return res;
    }
    T[] CreateArray<T>(int N, T value)
    {
        var res = new T[N];
        for (int i = 0; i < N; i++) res[i] = value;
        return res;
    }
    T[][] CreateArray<T>(int H, int W, T value)
    {
        var res = new T[H][];
        for (int i = 0; i < H; i++)
        {
            res[i] = new T[W];
            for (int j = 0; j < W; j++) res[i][j] = value;
        }
        return res;
    }
    T[][][] CreateArray<T>(int H, int W, int R, T value)
    {
        var res = new T[H][][];
        for (int i = 0; i < H; i++)
        {
            res[i] = new T[W][];
            for (int j = 0; j < W; j++)
            {
                res[i][j] = new T[R];
                for (int k = 0; k < R; k++) res[i][j][k] = value;
            }
        }
        return res;
    }

    Dictionary<int, List<int>> GetUnweightedAdjacencyList(int N, int M, bool isDirected, bool isNode_0indexed)
    {
        var dic = new Dictionary<int, List<int>>();
        foreach (var e in Enumerable.Range(0, N)) { dic.Add(e, new List<int>()); }
        for (int i = 0; i < M; i++)
        {
            var input = GetIntArray();
            var a = isNode_0indexed ? input[0] : input[0] - 1;
            var b = isNode_0indexed ? input[1] : input[1] - 1;
            dic[a].Add(b);
            if (isDirected == false) dic[b].Add(a);
        }
        return dic;
    }
    //Dictionary<int, List<(int node, long cost)>> GetWeightedAdjacencyList(int N, int M, bool isDirected, bool isNode_0indexed)
    //{
    //    var dic = new Dictionary<int, List<(int, long)>>();
    //    foreach (var e in Enumerable.Range(0, N)) { dic.Add(e, new List<(int, long)>()); }
    //    for (int i = 0; i < M; i++)
    //    {
    //        var input = GetIntArray();
    //        var a = isNode_0indexed ? input[0] : input[0] - 1;
    //        var b = isNode_0indexed ? input[1] : input[1] - 1;
    //        var c = input[2];
    //        dic[a].Add((b, c));
    //        if (isDirected == false) dic[b].Add((a, c));
    //    }
    //    return dic;
    //}

    bool eq<T, U>() => typeof(T).Equals(typeof(U));
    T ct<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
    T cv<T>(string s) => eq<T, int>() ? ct<T, int>(int.Parse(s))
                       : eq<T, long>() ? ct<T, long>(long.Parse(s))
                       : eq<T, double>() ? ct<T, double>(double.Parse(s))
                       : eq<T, char>() ? ct<T, char>(s[0])
                                         : ct<T, string>(s);
    void Multi<T>(out T a) => a = cv<T>(GetStr());
    void Multi<T, U>(out T a, out U b)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]);
    }
    void Multi<T, U, V>(out T a, out U b, out V c)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]);
    }
    void Multi<T, U, V, W>(out T a, out U b, out V c, out W d)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]);
    }
    void Multi<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]);
    }
    void Multi<T, U, V, W, X, Y>(out T a, out U b, out V c, out W d, out X e, out Y f)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]); f = cv<Y>(ar[5]);
    }

    void Output<T>(T t) => Console.WriteLine(t);
    void Output<T>(IList<T> ls) => Console.WriteLine(string.Join(" ", ls));
    void Debug<T>(IList<IList<T>> ls)
    {
        foreach (var l in ls)
            foreach (var s in l)
                Console.WriteLine(s);
    }

    void Swap<T>(ref T a, ref T b) { T temp = a; a = b; b = temp; }

    int[] dx = new int[] { 1, 0, -1, 0, 1, -1, -1, 1 };
    int[] dy = new int[] { 0, 1, 0, -1, 1, 1, -1, -1 };
    long mod = 1000000007;
}

partial class Program
{
    static void Main()
    {
        Console.SetIn(new StreamReader(Console.OpenStandardInput(8192)));
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Program().Solve();
        Console.Out.Flush();
        Console.Read();
    }

    public void Solve()
    {
        int T = GetInt();
        void SolveSolve()
        {
            int N = GetInt();
            var A = GetIntArray();
            var dict = new Dictionary<int,HashSet<int>>();
            for (int i = 0; i < N; i++) dict.Add(i, new HashSet<int>());
            for(int i = 0; i < N; i++)
            {
                for(int j = i + 1; j < N; j++)
                {
                    if (A[i] != A[j])
                    {
                        dict[i].Add(j);
                        dict[j].Add(i);
                    }
                }
            }

            var from = new int[N].Select(e => -1).ToArray();
            var queue = new Queue<int>();
            queue.Enqueue(0);
            while (queue.Count() > 0)
            {
                var now = queue.Dequeue();
                foreach (var next in dict[now])
                {
                    if (from[next] != -1) continue;
                    from[next] = now;
                    queue.Enqueue(next);
                }
            }

            if (from.Count(e => e == -1) > 1)
            {
                Output("NO");
                return;
            }
            Output("YES");
            for(int i = 1; i < N; i++)
            {
                Console.WriteLine((i+1)+" "+(from[i]+1));
            }
        }

        for(int i = 0; i < T; i++)
        {
            SolveSolve();
        }
    }

}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Policy;

public static class Ex
{
    public static bool IsNullOrEmpty(this string s) { return string.IsNullOrEmpty(s); }
    public static void yesno(this bool b) => Console.WriteLine(b ? "yes" : "no");
    public static void YesNo(this bool b) => Console.WriteLine(b ? "Yes" : "No");
    public static void YESNO(this bool b) => Console.WriteLine(b ? "YES" : "NO");
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    //public static bool Chmax<T>(ref this T a, T b) where T : struct, IComparable<T>
    //{
    //    if (b.CompareTo(a) > 0) { a = b; return true; }
    //    else return false;
    //}
    //[MethodImpl(MethodImplOptions.AggressiveInlining)]
    //public static bool Chmin<T>(ref this T a, T b) where T : struct, IComparable<T>
    //{
    //    if (b.CompareTo(a) < 0) { a = b; return true; }
    //    else return false;
    //}

    public static List<string> FastSort(this List<string> s) { s.Sort(StringComparer.OrdinalIgnoreCase); return s.ToList(); }

    public static int PopCount(this uint bits)
    {
        bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
        bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
        bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
        bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
        return (int)((bits & 0x0000ffff) + (bits >> 16 & 0x0000ffff));
    }
}

partial class Program
{
    string GetStr() { return Console.ReadLine().Trim(); }
    char GetChar() { return Console.ReadLine().Trim()[0]; }
    int GetInt() { return int.Parse(Console.ReadLine().Trim()); }
    long GetLong() { return long.Parse(Console.ReadLine().Trim()); }
    double GetDouble() { return double.Parse(Console.ReadLine().Trim()); }
    string[] GetStrArray() { return Console.ReadLine().Trim().Split(' '); }
    string[][] GetStrArray(int N)
    {
        var res = new string[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ');
        return res;
    }
    int[] GetIntArray() { return Console.ReadLine().Trim().Split(' ').Select(int.Parse).ToArray(); }
    int[][] GetIntArray(int N)
    {
        var res = new int[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(int.Parse).ToArray();
        return res;
    }
    public long[] GetLongArray() { return Console.ReadLine().Trim().Split(' ').Select(long.Parse).ToArray(); }
    long[][] GetLongArray(int N)
    {
        var res = new long[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(long.Parse).ToArray();
        return res;
    }
    char[] GetCharArray() { return Console.ReadLine().Trim().Split(' ').Select(char.Parse).ToArray(); }
    double[] GetDoubleArray() { return Console.ReadLine().Trim().Split(' ').Select(double.Parse).ToArray(); }
    double[][] GetDoubleArray(int N)
    {
        var res = new double[N][];
        for (int i = 0; i < N; i++) res[i] = Console.ReadLine().Trim().Split(' ').Select(double.Parse).ToArray();
        return res;
    }
    char[][] GetGrid(int H)
    {
        var res = new char[H][];
        for (int i = 0; i < H; i++) res[i] = Console.ReadLine().Trim().ToCharArray();
        return res;
    }
    T[] CreateArray<T>(int N, T value)
    {
        var res = new T[N];
        for (int i = 0; i < N; i++) res[i] = value;
        return res;
    }
    T[][] CreateArray<T>(int H, int W, T value)
    {
        var res = new T[H][];
        for (int i = 0; i < H; i++)
        {
            res[i] = new T[W];
            for (int j = 0; j < W; j++) res[i][j] = value;
        }
        return res;
    }
    T[][][] CreateArray<T>(int H, int W, int R, T value)
    {
        var res = new T[H][][];
        for (int i = 0; i < H; i++)
        {
            res[i] = new T[W][];
            for (int j = 0; j < W; j++)
            {
                res[i][j] = new T[R];
                for (int k = 0; k < R; k++) res[i][j][k] = value;
            }
        }
        return res;
    }

    Dictionary<int, List<int>> GetUnweightedAdjacencyList(int N, int M, bool isDirected, bool isNode_0indexed)
    {
        var dic = new Dictionary<int, List<int>>();
        foreach (var e in Enumerable.Range(0, N)) { dic.Add(e, new List<int>()); }
        for (int i = 0; i < M; i++)
        {
            var input = GetIntArray();
            var a = isNode_0indexed ? input[0] : input[0] - 1;
            var b = isNode_0indexed ? input[1] : input[1] - 1;
            dic[a].Add(b);
            if (isDirected == false) dic[b].Add(a);
        }
        return dic;
    }
    //Dictionary<int, List<(int node, long cost)>> GetWeightedAdjacencyList(int N, int M, bool isDirected, bool isNode_0indexed)
    //{
    //    var dic = new Dictionary<int, List<(int, long)>>();
    //    foreach (var e in Enumerable.Range(0, N)) { dic.Add(e, new List<(int, long)>()); }
    //    for (int i = 0; i < M; i++)
    //    {
    //        var input = GetIntArray();
    //        var a = isNode_0indexed ? input[0] : input[0] - 1;
    //        var b = isNode_0indexed ? input[1] : input[1] - 1;
    //        var c = input[2];
    //        dic[a].Add((b, c));
    //        if (isDirected == false) dic[b].Add((a, c));
    //    }
    //    return dic;
    //}

    bool eq<T, U>() => typeof(T).Equals(typeof(U));
    T ct<T, U>(U a) => (T)Convert.ChangeType(a, typeof(T));
    T cv<T>(string s) => eq<T, int>() ? ct<T, int>(int.Parse(s))
                       : eq<T, long>() ? ct<T, long>(long.Parse(s))
                       : eq<T, double>() ? ct<T, double>(double.Parse(s))
                       : eq<T, char>() ? ct<T, char>(s[0])
                                         : ct<T, string>(s);
    void Multi<T>(out T a) => a = cv<T>(GetStr());
    void Multi<T, U>(out T a, out U b)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]);
    }
    void Multi<T, U, V>(out T a, out U b, out V c)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]);
    }
    void Multi<T, U, V, W>(out T a, out U b, out V c, out W d)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]);
    }
    void Multi<T, U, V, W, X>(out T a, out U b, out V c, out W d, out X e)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]);
    }
    void Multi<T, U, V, W, X, Y>(out T a, out U b, out V c, out W d, out X e, out Y f)
    {
        var ar = GetStrArray(); a = cv<T>(ar[0]); b = cv<U>(ar[1]); c = cv<V>(ar[2]); d = cv<W>(ar[3]); e = cv<X>(ar[4]); f = cv<Y>(ar[5]);
    }

    void Output<T>(T t) => Console.WriteLine(t);
    void Output<T>(IList<T> ls) => Console.WriteLine(string.Join(" ", ls));
    void Debug<T>(IList<IList<T>> ls)
    {
        foreach (var l in ls)
            foreach (var s in l)
                Console.WriteLine(s);
    }

    void Swap<T>(ref T a, ref T b) { T temp = a; a = b; b = temp; }

    int[] dx = new int[] { 1, 0, -1, 0, 1, -1, -1, 1 };
    int[] dy = new int[] { 0, 1, 0, -1, 1, 1, -1, -1 };
    long mod = 1000000007;
}

partial class Program
{
    static void Main()
    {
        //Console.SetIn(new StreamReader(Console.OpenStandardInput(8192)));
        //Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Program().Solve();
        //Console.Out.Flush();
        Console.Read();
    }

    public void Solve()
    {
        int T = GetInt();
        for(int i = 0; i < T; i++)
        {
            SolveSolve();
        }
    }

    void SolveSolve()
    {
        int N = GetInt();
        var A = GetIntArray();
        var uf = new UnionFind(N);
        var path = new List<(int, int)>();
        for(int i = 0; i < N; i++)
        {
            for(int j = i + 1; j < N; j++)
            {
                if (A[i] == A[j]) continue;
                if (uf.Same(i, j) == false)
                {
                    uf.Union(i, j);
                    path.Add((i+1, j+1));
                }
            }
        }

        if (uf.TreeCount>1)
        {
            Output("NO");
            return;
        }
        Output("YES");
        foreach (var p in path) Console.WriteLine(p.Item1 + " " + p.Item2);
    }

    class UnionFind
    {
        int[] parents;
        public int TreeCount { get; private set; }
        public UnionFind(int n)
        {
            parents = new int[n];
            for (int i = 0; i < n; i++)
            {
                parents[i] = -1;
            }
            TreeCount = n;
        }

        public int Find(int x)
        {
            if (parents[x] < 0) return x;
            return parents[x] = Find(parents[x]);
        }

        public int Size(int x)
        {
            return -parents[Find(x)];
        }

        public bool Same(int x, int y)
        {
            return Find(x) == Find(y);
        }

        public bool Union(int x, int y)
        {
            x = Find(x);
            y = Find(y);
            if (x == y) return false;

            if (Size(x) < Size(y))
            {
                var tmp = x;
                x = y;
                y = tmp;
            }
            parents[x] += parents[y];
            parents[y] = x;
            TreeCount--;
            return true;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    class Dsu
    {
        private readonly int[] parent;

        public Dsu(int n)
        {
            parent = Enumerable.Range(0, n).ToArray();
        }

        public int FindSet(int v)
        {
            if (v == parent[v])
                return v;
            return parent[v] = FindSet(parent[v]);
        }

        public void UnionSets(int a, int b)
        {
            a = FindSet(a);
            b = FindSet(b);
            if (a != b)
                parent[b] = a;
        }
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadIntArray();
            var dsu = new Dsu(n);
            var ans = new List<(int, int)>();
            int c = n;
            for (int i = 0; i < n; i++)
                for (int j = i + 1; j < n; j++)
                    if (a[i] != a[j] && dsu.FindSet(i) != dsu.FindSet(j))
                    {
                        c--;
                        dsu.UnionSets(i, j);
                        ans.Add((i, j));
                    }
            if (c > 1)
                Write("NO");
            else
            {
                Write("YES");
                foreach (var t in ans)
                    Write(t.Item1 + 1, t.Item2 + 1);
            }
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


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

class D
{
	static int[] Read() => Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
	static long[] ReadL() => Array.ConvertAll(Console.ReadLine().Split(), long.Parse);
	static void Main() => Console.WriteLine(string.Join("\n", new int[int.Parse(Console.ReadLine())].Select(_ => Solve())));
	static string Solve()
	{
		var n = int.Parse(Console.ReadLine());
		var a = Read();

		if (a.Distinct().Count() == 1) return "NO";

		var r = new List<string>();

		var v2 = 0;
		for (int i = 1; i < n; i++)
		{
			if (a[i] != a[0])
			{
				r.Add($"1 {i + 1}");
				v2 = i;
			}
		}
		for (int i = 1; i < n; i++)
		{
			if (a[i] == a[0])
			{
				r.Add($"{v2 + 1} {i + 1}");
			}
		}

		return "YES\n" + string.Join("\n", r);
	}
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForces
{
    class Program
    {
        static void Main(string[] args)
        {
            int t = Convert.ToInt32(Console.ReadLine()); //número de testes
            for (int i = 0; i < t; i++)
            {
                int n = Convert.ToInt32(Console.ReadLine()); //número de districtos
                int[] gangs = Console.ReadLine().Split().Select(Int32.Parse).ToArray();
                int first= gangs[0];
                if(n > 1 && !Array.Exists(gangs, e => e != first))
                {
                    Console.WriteLine("NO");
                }
                else
                {
                    Console.WriteLine("YES");
                    List<string> results = new List<string>();
                    int b = 0;
                    int a = first;
                    for (int j = 1; j < n; j++)
                    {
                        if(gangs[j] != first)
                        {
                            b = j + 1;
                            results.Add(1 + " " + b);
                        }
                    }
                    for (int j = 1; j < n; j++)
                    {
                        if(gangs[j] == first)
                        {
                            a = j+1;
                            results.Add(b + " " + a);
                        }
                    }
                    foreach (string s in results)
                    {
                        Console.WriteLine(s);
                    }
                }
            }
            //Console.ReadKey();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CodeForces
{
    class Program
    {
        static void Main(string[] args)
        {
            int t = Convert.ToInt32(Console.ReadLine()); //número de testes
            for (int i = 0; i < t; i++)
            {
                int n = Convert.ToInt32(Console.ReadLine()); //número de districtos
                int[] gangs = Console.ReadLine().Split().Select(Int32.Parse).ToArray();
                int first= gangs[0];
                if(n > 1 && !Array.Exists(gangs, e => e != first))
                {
                    Console.WriteLine("NO");
                }
                else
                {
                    Console.WriteLine("YES");
                    List<string> results = new List<string>();
                    int b = 0;
                    int a = first;
                    for (int j = 1; j < n; j++)
                    {
                        if(gangs[j] != first)
                        {
                            b = j + 1;
                            results.Add(a + " " + b);
                        }
                    }
                    for (int j = 1; j < n; j++)
                    {
                        if(gangs[j] == first)
                        {
                            a = j+1;
                            results.Add(b + " " + a);
                        }
                    }
                    foreach (string s in results)
                    {
                        Console.WriteLine(s);
                    }
                }
            }
            //Console.ReadKey();
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static System.Math;
using System.Text;
using System.Threading;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Library;

namespace Program
{
    public static class ProblemD
    {
        static bool SAIKI = false;
        static public int numberOfRandomCases = 0;
        static public void MakeTestCase(List<string> _input, List<string> _output, ref Func<string[], bool> _outputChecker)
        {
        }
        static public void Solve()
        {
            var t = NN;
            for (var i = 0; i < t; i++)
            {
                var n = NN;
                var aList = NNList(n);
                if (aList.Distinct().Count() == 1) Console.WriteLine("NO");
                else
                {
                    Console.WriteLine("YES");
                    var minv = aList.Min();
                    var maxv = aList.Max();
                    var minidx = 0;
                    var maxidx = 0;
                    for (var j = 0; j < n; j++)
                    {
                        if (minv == aList[j]) minidx = j;
                        if (maxv == aList[j]) maxidx = j;
                    }
                    Console.WriteLine($"{minidx + 1} {maxidx + 1}");
                    for (var j = 0; j < n; j++)
                    {
                        if (j == minidx || j == maxidx) continue;
                        if (aList[j] == minv) Console.WriteLine($"{j + 1} {maxidx + 1}");
                        else Console.WriteLine($"{j + 1} {minidx + 1}");
                    }
                }
            }
        }
        class Printer : StreamWriter
        {
            public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
            public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { base.AutoFlush = false; }
            public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { base.AutoFlush = false; }
        }
        static LIB_FastIO fastio = new LIB_FastIODebug();
        static public void Main(string[] args) { if (args.Length == 0) { fastio = new LIB_FastIO(); Console.SetOut(new Printer(Console.OpenStandardOutput())); } if (SAIKI) { var t = new Thread(Solve, 134217728); t.Start(); t.Join(); } else Solve(); Console.Out.Flush(); }
        static long NN => fastio.Long();
        static double ND => fastio.Double();
        static string NS => fastio.Scan();
        static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray();
        static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray();
        static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray();
        static long Count<T>(this IEnumerable<T> x, Func<T, bool> pred) => Enumerable.Count(x, pred);
        static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n);
        static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c);
        static IOrderedEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x, _ => xorshift);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderBy<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderBy(x.OrderByRand(), selector);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x) => Enumerable.OrderByDescending(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderByDescending<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderByDescending(x.OrderByRand(), selector);
        static IOrderedEnumerable<string> OrderBy(this IEnumerable<string> x) => x.OrderByRand().OrderBy(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderBy(selector, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<string> OrderByDescending(this IEnumerable<string> x) => x.OrderByRand().OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderByDescending(selector, StringComparer.OrdinalIgnoreCase);
        static string Join<T>(this IEnumerable<T> x, string separator = "") => string.Join(separator, x);
        static uint xorshift { get { _xsi.MoveNext(); return _xsi.Current; } }
        static IEnumerator<uint> _xsi = _xsc();
        static IEnumerator<uint> _xsc() { uint x = 123456789, y = 362436069, z = 521288629, w = (uint)(DateTime.Now.Ticks & 0xffffffff); while (true) { var t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); yield return w; } }
        static bool Chmax<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) < 0) { lhs = rhs; return true; } return false; }
        static bool Chmin<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) > 0) { lhs = rhs; return true; } return false; }
        static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value);
        static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value);
        static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value);
        static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value);
    }
}
namespace Library {
    class LIB_FastIO
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIO() { str = Console.OpenStandardInput(); }
        readonly Stream str;
        readonly byte[] buf = new byte[2048];
        int len, ptr;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        byte read()
        {
            if (ptr >= len)
            {
                ptr = 0;
                if ((len = str.Read(buf, 0, 2048)) <= 0)
                {
                    return 0;
                }
            }
            return buf[ptr++];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        char Char()
        {
            byte b = 0;
            do b = read();
            while (b < 33 || 126 < b);
            return (char)b;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public long Long()
        {
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != '-' && (b < '0' || '9' < b));
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = (ret << 3) + (ret << 1) + b - '0';
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public double Double() { return double.Parse(Scan(), CultureInfo.InvariantCulture); }
    }
    class LIB_FastIODebug : LIB_FastIO
    {
        Queue<string> param = new Queue<string>();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIODebug() { }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override string Scan() => NextString();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override long Long() => long.Parse(NextString());
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override double Double() => double.Parse(NextString());
    }
}


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

namespace Mycop
{
    class Program
    {
        static void Main()
        {
            var t = int.Parse(Console.ReadLine());
            var results = new (int, int)[t][];

            for (var i = 0; i < t; i++)
            {
                var n = int.Parse(Console.ReadLine());
                var zones = Console.ReadLine().Split().Select(int.Parse).ToArray();

                var bands = zones.Distinct().ToDictionary(zone => zone, zone => new List<int>());
                for (var j = 0; j < n; j++)
                    bands[zones[j]].Add(j);

                var smallestCount = bands.Min(bands => bands.Value.Count);

                if (smallestCount == n)
                    continue;

                var smallestBand = bands.First(band => band.Value.Count == smallestCount);
                bands.Remove(smallestBand.Key);

                var result = new (int, int)[n - 1];
                var k = 0;
                foreach (var band in bands)
                    foreach (var zone in band.Value)
                        result[k++] = (smallestBand.Value[0], zone);

                foreach (var zone in smallestBand.Value.Skip(1))
                    result[k++] = (result[0].Item2, zone);

                results[i] = result;
            }

            foreach (var r in results)
            {
                if (r == null)
                    Console.WriteLine("NO");
                else
                {
                    Console.WriteLine("YES");
                    foreach (var road in r)
                    {
                        Console.WriteLine($"{road.Item1 + 1} {road.Item2 + 1}");
                    }
                }
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using static System.Math;

namespace CSharpSpiral {
	class Program {
		public static void Main(string[] args) {
			var sw = new StreamWriter(Console.OpenStandardOutput()) {
				AutoFlush =
#if DEBUG
			true
#else
			false
#endif
			};
			Console.SetOut(sw);
			new Program().Solve(new ConsoleInput(
#if DEBUG
			new StreamReader("../../../inputData.txt")
#else
			Console.In
#endif
			, ' '));
			Console.Out.Flush();
		}

		public void Solve(ConsoleInput cin) {
			var T = cin.ReadInt;
			for(int t = 0; t < T; t++) {
				var N = cin.ReadInt;
				var F = new UnionFindForest(N);
				var gangRep = new Dictionary<int, int>();
				var A = cin.ReadIntArray(N);
				for(int i = 0; i < N; i++) {
					var ai = A[i];
					if(!gangRep.ContainsKey(ai)) {
						gangRep.Add(ai, i);
					} else {
						F.Union(i, gangRep[ai]);
					}
				}
				if(gangRep.Count() <= 1) {
					Console.WriteLine("NO");
					continue;
				}
				Console.WriteLine("YES");
				var arr = Enumerable.Repeat(-1, N).ToArray();
				var second = Enumerable.Range(1, N-1).First(i => !F.Find(i, 0));
				for(int i = 1; i < N; i++) {
					if(!F.Find(i, 0)) {
						arr[i] = 0;
					} else {
						arr[i] = second;
					}
				}
				for(int i = 1; i < N; i++) {
					Console.WriteLine($"{arr[i]+1} {i+1}");
				}
			}
		}
	}

	static class ExtendClass {
		public static string Join<T>(this IEnumerable<T> X, string separator = " ")
			=> string.Join(separator, X);
	}
	class ConsoleInput {
		private readonly TextReader _stream;
		private readonly char _separator = ' ';
		private readonly Queue<string> inputStream;
		public ConsoleInput(TextReader stream, char separator = ' ') {
			this._separator = separator;
			this._stream = stream;
			inputStream = new Queue<string>();
		}
		public string Read {
			get {
				if(inputStream.Count != 0) return inputStream.Dequeue();
				string[] tmp = _stream.ReadLine().Split(_separator);
				for(int i = 0; i < tmp.Length; ++i)
					inputStream.Enqueue(tmp[i]);
				return inputStream.Dequeue();
			}
		}
		public string ReadLine { get { return _stream.ReadLine(); } }
		public int ReadInt { get { return int.Parse(Read); } }
		public long ReadLong { get { return long.Parse(Read); } }
		public double ReadDouble { get { return double.Parse(Read); } }
		public string[] ReadStrArray(long N) {
			var ret = new string[N];
			for(long i = 0; i < N; ++i)
				ret[i] = Read;
			return ret;
		}
		public int[] ReadIntArray(long N) { var ret = new int[N]; for(long i = 0; i < N; ++i) ret[i] = ReadInt; return ret; }
		public long[] ReadLongArray(long N) { var ret = new long[N]; for(long i = 0; i < N; ++i) ret[i] = ReadLong; return ret; }
		public double[] ReadDoubleArray(long N) { var ret = new double[N]; for(long i = 0; i < N; ++i) ret[i] = ReadDouble; return ret; }
		public bool isEOF {
			get { return _stream.Peek() == -1; }
		}
	}
	class UnionFindForest {
		public class Node {
			public int value { get; set; }
			public virtual Node parent { get; set; }
			public virtual Node root {
				get {
					var path = new Queue<Node>();
					var res = this;
					while(res.parent != res) {
						path.Enqueue(res);
						res = res.parent;
					}
					while(path.Any())
						path.Dequeue().parent = res;
					return res;
				}
			}
			public int rank { get; private set; }    //meanful iff root
			public void rankIncrement() => rank++;
			public Node(int _value) {
				value = _value;
				parent = this;
				rank = 1;
			}
		}

		private readonly Dictionary<int, Node> Registry = new Dictionary<int, Node>();
		public UnionFindForest(int N) {
			for(int i = 0; i < N; i++) Add(i);
		}
		public void Union(int x, int y) => Union(Registry[x], Registry[y]);
		public void Union(Node X, Node Y) {
			var RX = X.root;
			var RY = Y.root;
			switch(RX.rank.CompareTo(RY.rank)) {
				case 1:
					RY.parent = RX;
					break;
				case -1:
					RX.parent = RY;
					break;
				default:
					RX.parent = RY;
					RY.rankIncrement();
					break;
			}
		}
		public bool Find(int x, int y) => Find(Registry[x], Registry[y]);
		public bool Find(Node X, Node Y) => X.root == Y.root;
		public virtual void Add(int id) {
			var n = new Node(id);
			Registry.Add(id, n);
		}
		public Dictionary<Node, int> TallyDegrees() {
			var Roots = new Dictionary<Node, int>();
			foreach(var node in Registry.Values) {
				if(Roots.Keys.Contains(node.root))
					Roots[node.root]++;
				else
					Roots.Add(node.root, 1);
			}
			return Roots;
		}
		public int[] Degrees() {
			var D = TallyDegrees();
			var res = new int[Registry.Count];
			for(int i = 0; i < Registry.Count; i++)
				res[i] = D[Registry[i].root];
			return res;
		}
		public int TreeCount() {
			var D = TallyDegrees();
			return D.Count;
		}
	}
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using static System.Math;

namespace CSharpSpiral {
	using Graph;
	class Program {
		public static void Main(string[] args) {
			var sw = new StreamWriter(Console.OpenStandardOutput()) {
				AutoFlush =
#if DEBUG
			true
#else
			false
#endif
			};
			Console.SetOut(sw);
			new Program().Solve(new ConsoleInput(
#if DEBUG
			new StreamReader("../../../inputData.txt")
#else
			Console.In
#endif
			, ' '));
			Console.Out.Flush();
		}

		public void Solve(ConsoleInput cin) {
			var T = cin.ReadInt;
			for(int t = 0; t < T; t++) {
				var N = cin.ReadInt;
				var F = new UnionFindForest(N);
				var gangRep = new Dictionary<int, int>();
				var A = cin.ReadIntArray(N);
				for(int i = 0; i < N; i++) {
					var ai = A[i];
					if(!gangRep.ContainsKey(ai)) {
						gangRep.Add(ai, i);
					} else {
						F.Union(i, gangRep[ai]);
					}
				}
				if(gangRep.Count() <= 1) {
					Console.WriteLine("NO");
					continue;
				}
				Console.WriteLine("YES");
				var arr = Enumerable.Repeat(-1, N).ToArray();
				var second = Enumerable.Range(1, N-1).First(i => !F.Find(i, 0));
				for(int i = 1; i < N; i++) {
					if(!F.Find(i, 0)) {
						arr[i] = 0;
					} else {
						arr[i] = second;
					}
				}
				for(int i = 1; i < N; i++) {
					Console.WriteLine($"{arr[i]+1} {i+1}");
				}
			}
		}
	}

	static class ExtendClass {
		public static string Join<T>(this IEnumerable<T> X, string separator = " ")
			=> string.Join(separator, X);
	}
	class ConsoleInput {
		private readonly TextReader _stream;
		private readonly char _separator = ' ';
		private readonly Queue<string> inputStream;
		public ConsoleInput(TextReader stream, char separator = ' ') {
			this._separator = separator;
			this._stream = stream;
			inputStream = new Queue<string>();
		}
		public string Read {
			get {
				if(inputStream.Count != 0) return inputStream.Dequeue();
				string[] tmp = _stream.ReadLine().Split(_separator);
				for(int i = 0; i < tmp.Length; ++i)
					inputStream.Enqueue(tmp[i]);
				return inputStream.Dequeue();
			}
		}
		public string ReadLine { get { return _stream.ReadLine(); } }
		public int ReadInt { get { return int.Parse(Read); } }
		public long ReadLong { get { return long.Parse(Read); } }
		public double ReadDouble { get { return double.Parse(Read); } }
		public string[] ReadStrArray(long N) {
			var ret = new string[N];
			for(long i = 0; i < N; ++i)
				ret[i] = Read;
			return ret;
		}
		public int[] ReadIntArray(long N) { var ret = new int[N]; for(long i = 0; i < N; ++i) ret[i] = ReadInt; return ret; }
		public long[] ReadLongArray(long N) { var ret = new long[N]; for(long i = 0; i < N; ++i) ret[i] = ReadLong; return ret; }
		public double[] ReadDoubleArray(long N) { var ret = new double[N]; for(long i = 0; i < N; ++i) ret[i] = ReadDouble; return ret; }
		public bool isEOF {
			get { return _stream.Peek() == -1; }
		}
	}
	class UnionFindForest {
		public class Node {
			public int value { get; set; }
			public virtual Node parent { get; set; }
			public virtual Node root {
				get {
					var path = new Queue<Node>();
					var res = this;
					while(res.parent != res) {
						path.Enqueue(res);
						res = res.parent;
					}
					while(path.Any())
						path.Dequeue().parent = res;
					return res;
				}
			}
			public int rank { get; private set; }    //meanful iff root
			public void rankIncrement() => rank++;
			public Node(int _value) {
				value = _value;
				parent = this;
				rank = 1;
			}
		}

		private readonly Dictionary<int, Node> Registry = new Dictionary<int, Node>();
		public UnionFindForest(int N) {
			for(int i = 0; i < N; i++) Add(i);
		}
		public void Union(int x, int y) => Union(Registry[x], Registry[y]);
		public void Union(Node X, Node Y) {
			var RX = X.root;
			var RY = Y.root;
			switch(RX.rank.CompareTo(RY.rank)) {
				case 1:
					RY.parent = RX;
					break;
				case -1:
					RX.parent = RY;
					break;
				default:
					RX.parent = RY;
					RY.rankIncrement();
					break;
			}
		}
		public bool Find(int x, int y) => Find(Registry[x], Registry[y]);
		public bool Find(Node X, Node Y) => X.root == Y.root;
		public virtual void Add(int id) {
			var n = new Node(id);
			Registry.Add(id, n);
		}
		public Dictionary<Node, int> TallyDegrees() {
			var Roots = new Dictionary<Node, int>();
			foreach(var node in Registry.Values) {
				if(Roots.Keys.Contains(node.root))
					Roots[node.root]++;
				else
					Roots.Add(node.root, 1);
			}
			return Roots;
		}
		public int[] Degrees() {
			var D = TallyDegrees();
			var res = new int[Registry.Count];
			for(int i = 0; i < Registry.Count; i++)
				res[i] = D[Registry[i].root];
			return res;
		}
		public int TreeCount() {
			var D = TallyDegrees();
			return D.Count;
		}
	}
}


using System;
using System.Collections.Generic;

namespace olympiada
{
    class Program
    {
        static void Merge(int[] array, int lowIndex, int middleIndex, int highIndex)
        {
            var left = lowIndex;
            var right = middleIndex + 1;
            var tempArray = new int[highIndex - lowIndex + 1];
            var tempB = new int[highIndex - lowIndex + 1];
            var index = 0;

            while ((left <= middleIndex) && (right <= highIndex))
            {
                if (array[left] < array[right])
                {
                    tempArray[index] = array[left];
                    left++;
                }
                else
                {
                    tempArray[index] = array[right];
                    right++;
                }

                index++;
            }

            for (var i = left; i <= middleIndex; i++)
            {
                tempArray[index] = array[i];
                index++;
            }

            for (var i = right; i <= highIndex; i++)
            {
                tempArray[index] = array[i];
                index++;
            }

            for (var i = 0; i < tempArray.Length; i++)
            {
                array[lowIndex + i] = tempArray[i];
            }
        }

        static int[] MergeSort(int[] array, int lowIndex, int highIndex)
        {
            if (lowIndex < highIndex)
            {
                var middleIndex = (lowIndex + highIndex) / 2;
                MergeSort(array, lowIndex, middleIndex);
                MergeSort(array, middleIndex + 1, highIndex);
                Merge(array, lowIndex, middleIndex, highIndex);
            }

            return array;
        }

        static int[] MergeSort(int[] array)
        {
            return MergeSort(array, 0, array.Length - 1);
        }
        static void Main(string[] args)
        {
            int t = int.Parse(Console.ReadLine());
            for(int q=0; q<t; q++)
            {
                int n = int.Parse(Console.ReadLine());
                string[] arr0 = Console.ReadLine().Split(new char[] { ' ' });
                int[] arr = new int[n];
                for(int i=0; i<n; i++)
                {
                    arr[i] = int.Parse(arr0[i]);
                }
                bool k = false;
                for (int i = 1; i < n; i++)
                {
                    if (arr[i] != arr[0])
                    {
                        k = true;
                        break;
                    }
                }
                if (!k)
                {
                    Console.WriteLine("NO");
                }
                else
                {
                    bool[] b = new bool[n];
                    b[0] = true;
                    int ne = -1;
                    Console.WriteLine("YES");
                    for(int i=1; i<n; i++)
                    {
                        if (arr[0] != arr[i])
                        {
                            Console.WriteLine("1 " + (i + 1));
                            ne = i;
                            b[i] = true;
                        }
                        else
                        {
                            b[i] = false;
                        }
                    }
                    for (int i = 1; i < n; i++)
                    {
                        if (!b[i])
                        {
                            Console.WriteLine((i+1)+" "+(ne+1));
                        }
                    }
                }

            }
        }
    }
}


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

namespace ConsoleApp14
{
    class Program
    {
        static void Main(string[] args)
        {
            var t = int.Parse(Console.ReadLine());

            while (t-- > 0)
            {
                var n = int.Parse(Console.ReadLine());
                var dist = Console.ReadLine().Split(' ');

                if (dist.Distinct().Count() == 1) { Console.WriteLine("NO"); continue; }
                var liste = new List<int>();
                foreach (var a in dist) { liste.Add(int.Parse(a)); }

                var x = -1;
                var c = 0;
                var d = 0;

                Console.WriteLine("YES");

                for (var i = 1; i < n; i++)
                {
                    if (liste[i] != liste[0]) { x = i; break; }

                }
                d = x + 1;

                Console.WriteLine("1 " + d);

                for (var i = 1;  i < n ; i++)
                {
                    if (i == x) { continue; }
                    c = i + 1;
                    if (liste[i] != liste[0]) {  Console.WriteLine("1 " + c); }
                    else { Console.WriteLine(d + " " + c); }

                }

            }
            Console.ReadLine();

        }
    }
}


using System;

class Program
{
    static long fact(long val)
    {
        return val > 2 ? val * fact(val - 1) : val;
    }

    static void Main()
    {
        long val = long.Parse(Console.ReadLine());
        long v1 = fact(val / 2);
        long v2 = fact(val / 2 - 1);
        Console.WriteLine((fact(val) / (v1 * v1) * v2 * v2 / 2));
    }
}


using System;
using System.Linq;
using System.Text;

class Program
{
    private static StringBuilder _buffer = new StringBuilder();

    static void Run()
    {
        _ = Console.ReadLine();
        var groups = Console.ReadLine().Split(' ').Select((x, i) => (int.Parse(x), i + 1)).GroupBy(x => x.Item1).ToArray();

        if (groups.Count() > 1)
        {
            _buffer.AppendLine("YES");
            int first = groups[0].First().Item2;
            for (int i = 0, k = 1; k < groups.Length; i++, k++)
            {
                foreach (var second in groups[k])
                    _buffer.AppendLine(first + " " + second.Item2);
                first = groups[k].First().Item2;
            }
            foreach (var second in groups[0].Skip(1))
                _buffer.AppendLine(first + " " + second.Item2);
        }
        else
            _buffer.AppendLine("NO");
    }

    static void Main()
    {
        for (int i = int.Parse(Console.ReadLine()); i > 0; i--) Run();
        Console.WriteLine(_buffer);
    }
}


using System;
using System.Linq;
using System.Text;

class Program
{
    private static StringBuilder _buffer = new StringBuilder();

    static void Run()
    {
        _ = Console.ReadLine();
        var groups = Console.ReadLine().Split(' ').Select((x, i) => (int.Parse(x), i + 1)).GroupBy(x => x.Item1).ToArray();

        if (groups.Count() > 1)
        {
            _buffer.AppendLine("YES");
            int first = 0;
            for (int i = 0, k = 1; k < groups.Length; i++, k++)
            {
                first = groups[i].First().Item2;
                foreach (var second in groups[k])
                    _buffer.AppendLine(first + " " + second.Item2);
            }
            foreach (var second in groups[0].Skip(1))
                _buffer.AppendLine(first + " " + second.Item2);
        }
        else
            _buffer.AppendLine("NO");
    }

    static void Main()
    {
        for (int i = int.Parse(Console.ReadLine()); i > 0; i--) Run();
        Console.WriteLine(_buffer);
    }
}


using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;

namespace ProblemD
{
	internal class ProblemD
	{
		private static void dfs(bool[] visited, int n, int[] a, List<int> rs, List<int> rf, int node )
		{
			if (visited[node])
			{
				return;
			}

			visited[node] = true;
			for (var i = 0; i < n; ++i)
			{
				if (!visited[i] && a[node] != a[i])
				{
					rs.Add(node);
					rf.Add(i);
					dfs(visited, n,a, rs, rf,i);
				}
			}
		}
		public static void Main(string[] args)
		{
			var t = int.Parse(Console.ReadLine());
			for (var tt = 0; tt < t; ++tt)
			{
				var n = int.Parse(Console.ReadLine());
				var a = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();

				var visited = new bool[n];
				var rs = new List<int>();
				var rf = new List<int>();
				dfs(visited, n, a, rs, rf, 0);
				if (visited.All(x => x))
				{
					Console.WriteLine("YES");
					for (var i = 0; i < rs.Count; ++i)
					{
						Console.WriteLine((rs[i] +1).ToString() + " " + (rf[i]+1).ToString());
					}
				}
				else
				{
					Console.WriteLine("NO");
				}
			}
		}
	}
}


/* Date: 23.10.2020 *  Time: 22:45 */
//
// CF 677 D
//
//

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

class Example
{
# if ( ! ONLINE_JUDGE )
	public static StreamReader sr = new StreamReader ("C:\\TRR\\2020\\Task\\07 Codeforces\\050\\D.TXT");
	public static StreamWriter sw = new StreamWriter ("C:\\TRR\\2020\\Task\\07 Codeforces\\050\\OUTPUT.OUT");
# endif

# if ( ! ONLINE_JUDGE )
	public static void Print (int [] a, string title)
	{
		sw.WriteLine ("*** " + title);
		sw.Write ("***");
		for ( int i=0; i < a.Length; i++ )
			sw.Write (" " + a [i]);
		sw.WriteLine ();
	}
# endif
	public static void Main (string[] args)
	{
		NumberFormatInfo nfi = NumberFormatInfo.InvariantInfo;

		int q;

# if ( ONLINE_JUDGE )
		q = int.Parse (Console.ReadLine ());
# else
		q = int.Parse (sr.ReadLine ());
		sw.WriteLine ("*** TEST = " + q);
# endif

		for ( int _q=0; _q < q; _q++ )
		{
			string s;
			int n;

# if ( ONLINE_JUDGE )
			n = int.Parse (Console.ReadLine ());
			s = (Console.ReadLine ());
# else
			sw.WriteLine ("*** # " + _q);
			n = int.Parse (sr.ReadLine ());
			s = (sr.ReadLine ());
# endif

			int [] a = new int [n];
			{
				string [] ss = s.Split (' ');
				for ( int i=0; i < n; i++ )
					a [i] = int.Parse (ss [i]);
			}

# if ( ! ONLINE_JUDGE )
			sw.WriteLine ("*** n = " + n);
			sw.Write ("***");
			for ( int i=0; i < n; i++ )
				sw.Write (" " + a [i]);
			sw.WriteLine ();
# endif

			int i1 = -1;
			for ( int i=1; i < n; i++ )
				if ( a [i] != a [0] )
				{
					i1 = i;
					break;
				}

			bool ok = i1 > -1;

# if ( ONLINE_JUDGE )
			if ( ok )
			{
				Console.WriteLine ("YES");
				for ( int i=1; i < n; i++ )
					if ( a [i] != a [0] )
						Console.WriteLine ("1 " + (i+1));
					else
						Console.WriteLine ((i1 + 1) + " " + (i+1));
			}
			else
				Console.WriteLine ("NO");
# else
			if ( ok )
			{
				sw.WriteLine ("YES");
				for ( int i=1; i < n; i++ )
					if ( a [i] != a [0] )
						sw.WriteLine ("1 " + (i+1));
					else
						sw.WriteLine ((i1 + 1) + " " + (i+1));
			}
			else
				sw.WriteLine ("NO");
# endif
		}

# if ( ! ONLINE_JUDGE )
		sw.Close ();
# endif
	}
}


using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var n = int.Parse(Console.ReadLine());
            for (; n > 0; n--)
            {
                Console.ReadLine();
                var a = Console.ReadLine().Split(' ').Select(int.Parse).ToList();
                List<int> same = new List<int>();
                if(a.Min() == a.Max())
                {
                    Console.WriteLine("NO");
                }
                else
                {
                    var dif = -1;
                    for(int i = 1; i < a.Count; i++)
                    {
                        if(a[0] == a[i])
                        {
                            same.Add(i);
                        }
                        else
                        {
                            Console.WriteLine(1 + " " + (i + 1));
                            dif = i;
                        }
                    }
                    for(int i = 0; i < same.Count; i++)
                    {
                        Console.WriteLine((dif + 1) + " " + (same[i] + 1));
                    }
                }
            }
        }
    }
}


using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp9
{
    class Program
    {
        static void Main(string[] args)
        {
            var n = int.Parse(Console.ReadLine());
            for (; n > 0; n--)
            {
                Console.ReadLine();
                var a = Console.ReadLine().Split(' ').Select(int.Parse).ToList();
                List<int> same = new List<int>();
                if(a.Min() == a.Max())
                {
                    Console.WriteLine("NO");
                }
                else
                {
                    Console.WriteLine("YES");
                    var dif = -1;
                    for(int i = 1; i < a.Count; i++)
                    {
                        if(a[0] == a[i])
                        {
                            same.Add(i);
                        }
                        else
                        {
                            Console.WriteLine(1 + " " + (i + 1));
                            dif = i;
                        }
                    }
                    for(int i = 0; i < same.Count; i++)
                    {
                        Console.WriteLine((dif + 1) + " " + (same[i] + 1));
                    }
                }
            }
        }
    }
}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: v!([]), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = v!([8]);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn vvb(&mut self, r: usize, c: Option<usize>) -> Vec<Vec<u8>> {
		let mut res = v!([r]);
		let c = c.unwrap_or(0);
		rep!{[r]
			let t = self.vb();
			assert!(c == 0 || t.len() == c);
			res.push(t);
		}
		res
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
}
//------------------- End rusT }}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	rep!{[rin.u()]
		let n = rin.u();
		let mut a = v!([n]);
		for i in 0..n {
			a.push( (rin.u(),i+1) );
		}
		a.sort();
		if a[0].0 == a[n-1].0 {
			writeln!(rout, "NO").ok();
			continue;
		}
		writeln!(rout, "YES").ok();
		for i in 1..n {
			if a[i].0 == a[0].0 {
				writeln!(rout, "{} {}", a[i].1, a[n-1].1).ok();
			} else {
				writeln!(rout, "{} {}", a[0].1, a[i].1).ok();
			}
		}
	}
}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! min {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b < *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! max {
	($x:expr,$y:expr) => {{ let b=$y; let a=&mut$x; if b > *a {*a=b; true} else {false} }};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: v!([]), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = v!([8]);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn vvb(&mut self, r: usize, c: Option<usize>) -> Vec<Vec<u8>> {
		let mut res = v!([r]);
		let c = c.unwrap_or(0);
		rep!{[r]
			let t = self.vb();
			assert!(c == 0 || t.len() == c);
			res.push(t);
		}
		res
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
}
//------------------- End rusT }}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	rep!{[rin.u()]
		let n = rin.u();
		let mut a = rin.vi(n);
		a.sort();
		if a[0] == a[n-1] {
			writeln!(rout, "NO").ok();
			continue;
		}
		writeln!(rout, "YES").ok();
		writeln!(rout, "1 {}", n).ok();
		for i in 1..n-1 {
			if a[i] == a[0] {
				writeln!(rout, "{} {}", i+1, n).ok();
			} else {
				writeln!(rout, "1 {}", i+1).ok();
			}
		}
	}
}


#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
#![allow(unused_mut)]
#![allow(unused_variables)]
#![allow(dead_code)]

#[allow(unused_macros)]
macro_rules! invec {
    ( $ t : ty ) => {{
        let mut s = String::new();
        match std::io::stdin().read_line(&mut s) {
            Ok(0) => Vec::<$t>::new(),
            Ok(n) => s
                .trim()
                .split_whitespace()
                .map(|s| s.parse::<$t>().unwrap())
                .collect::<Vec<$t>>(),
            Err(_) => Vec::<$t>::new(),
        }
    }};
}

#[allow(unused_macros)]
macro_rules! get {
      ($t:ty) => {
          {
              let mut line: String = String::new();
              std::io::stdin().read_line(&mut line).unwrap();
              line.trim().parse::<$t>().unwrap()
          }
      };
      ($($t:ty),*) => {
          {
              let mut line: String = String::new();
              std::io::stdin().read_line(&mut line).unwrap();
              let mut iter = line.split_whitespace();
              (
                  $(iter.next().unwrap().parse::<$t>().unwrap(),)*
              )
          }
      };
      ($t:ty; $n:expr) => {
          (0..$n).map(|_|
              get!($t)
          ).collect::<Vec<_>>()
      };
      ($($t:ty),*; $n:expr) => {
          (0..$n).map(|_|
              get!($($t),*)
          ).collect::<Vec<_>>()
      };
      ($t:ty ;;) => {
          {
              let mut line: String = String::new();
              std::io::stdin().read_line(&mut line).unwrap();
              line.split_whitespace()
                  .map(|t| t.parse::<$t>().unwrap())
                  .collect::<Vec<_>>()
          }
      };
      ($t:ty ;; $n:expr) => {
          (0..$n).map(|_| get!($t ;;)).collect::<Vec<_>>()
      };
}

#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let mut s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
    ($iter:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($next:expr, [$t:tt]) => {
        {
            let len = read_value!($next, usize);
            (0..len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
        }
    };
    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

#[allow(unused_macros)]
#[cfg(debug_assertions)]
macro_rules! mydbg {
    //($arg:expr) => (dbg!($arg))
    //($arg:expr) => (println!("{:?}",$arg));
      ($($a:expr),*) => {
          eprintln!(concat!($(stringify!($a), " = {:?}, "),*), $($a),*);
      }
}
#[cfg(not(debug_assertions))]
macro_rules! mydbg {
    ($($arg:expr),*) => {};
}

macro_rules! echo {
    ($($a:expr),*) => {
          $(println!("{}",$a))*
      }
}

use std::cmp::*;
use std::collections::*;
use std::ops::{Add, Div, Mul, Sub};

#[allow(dead_code)]
static INF_I64: i64 = i64::max_value() / 2;
#[allow(dead_code)]
static INF_I32: i32 = i32::max_value() / 2;
#[allow(dead_code)]
static INF_USIZE: usize = usize::max_value() / 2;
#[allow(dead_code)]
static M_O_D: usize = 1000000007;
#[allow(dead_code)]
static PAI: f64 = 3.1415926535897932;

trait IteratorExt: Iterator {
    fn toVec(self) -> Vec<Self::Item>;
}

impl<T: Iterator> IteratorExt for T {
    fn toVec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

trait CharExt {
    fn toNum(&self) -> usize;
    fn toAlphabetIndex(&self) -> usize;
    fn toNumIndex(&self) -> usize;
}
impl CharExt for char {
    fn toNum(&self) -> usize {
        return *self as usize;
    }
    fn toAlphabetIndex(&self) -> usize {
        return self.toNum() - 'a' as usize;
    }
    fn toNumIndex(&self) -> usize {
        return self.toNum() - '0' as usize;
    }
}

trait VectorExt {
    fn joinToString(&self, s: &str) -> String;
}
impl<T: ToString> VectorExt for Vec<T> {
    fn joinToString(&self, s: &str) -> String {
        return self
            .iter()
            .map(|x| x.to_string())
            .collect::<Vec<_>>()
            .join(s);
    }
}

trait StringExt {
    fn get_reverse(&self) -> String;
}
impl StringExt for String {
    fn get_reverse(&self) -> String {
        self.chars().rev().collect::<String>()
    }
}

trait UsizeExt {
    fn pow(&self, n: usize) -> usize;
}
impl UsizeExt for usize {
    fn pow(&self, n: usize) -> usize {
        return ((*self as u64).pow(n as u32)) as usize;
    }
}

fn main() {
    let T = get!(usize);
    for testcase in 0..T {
        mydbg!(testcase);
        let mut ans: u64 = 0;
        let N = get!(usize);
        let a = invec!(u64);
        let mut h = HashMap::new();
        for i in 0..N {
            let item = a[i];
            let mut hp = h.entry(item).or_insert(vec![]);
            hp.push(i + 1);
        }
        if h.len() == 1 {
            echo!("NO");
        } else {
            let l = h.len();
            let mut map = vec![vec![]; l];
            let mut p = 0;
            let mut parent = vec![0; l];
            for (_, index) in &h {
                let k = index[0];
                parent[p] = k;

                for i in 1..index.len() {
                    map[(p + 1) % l].push(index[i]);
                }
                p += 1;
            }
            let mut ans = vec![];
            for i in 1..l {
                ans.push(format!("{} {}", parent[i], parent[i - 1]));
            }
            for i in 0..l {
                for j in 0..map[i].len() {
                    ans.push(format!("{} {}", parent[i], map[i][j]));
                }
            }

            echo!("YES");
            echo!(ans.joinToString("\n"));
        }
    }
}


use std::io::{self, Write};
use std::{fmt, ops, str};

macro_rules! read {
    ( $t:ty ) => {{
        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();
        input.trim_end().parse::<$t>().ok().unwrap()
    }};
    ( $( $t:ty ),* ) => {{
        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();
        let mut iter = input.split_whitespace();
        ( $( iter.next().unwrap().parse::<$t>().unwrap() ),* )
    }};
}

struct Ios(Vec<char>);

impl str::FromStr for Ios {
    type Err = ();

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Ios(s.trim_end().chars().collect()))
    }
}

impl fmt::Display for Ios {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0.iter().collect::<String>())
    }
}

struct Iov<T>(Vec<T>);

impl<T: str::FromStr> str::FromStr for Iov<T> {
    type Err = T::Err;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let iter = s.split_whitespace();
        Ok(Iov(iter.map(|x| x.parse()).collect::<Result<_, _>>()?))
    }
}

impl<T: fmt::Display> fmt::Display for Iov<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}",
            self.0.iter().map(|x| x.to_string())
                .collect::<Vec<_>>().join(" ")
        )
    }
}

impl<T> ops::Index<usize> for Iov<T> {
    type Output = T;

    fn index(&self, i: usize) -> &Self::Output {
        self.0.get(i - 1).unwrap()
    }
}

fn solve(writer: &mut io::BufWriter<io::StdoutLock>) {
    let n = read!(usize);
    let a = read!(Iov<i32>);

    if (1..n).all(|i| a[i] == a[i + 1]) {
        writeln!(writer, "NO").ok();
        return;
    }
    writeln!(writer, "YES", ).ok();

    let mut k = 0;
    for i in 2..=n {
        if a[i] == a[1] { continue; }
        k = i;
        writeln!(writer, "{} {}", 1, i).ok();
    }
    for i in 2..=n {
        if a[i] != a[1] { continue; }
        writeln!(writer, "{} {}", k, i).ok();
    }
}

fn main() {
    let stdout = io::stdout();
    let mut writer = io::BufWriter::new(stdout.lock());
    for _ in 0..read!(usize) { solve(&mut writer); }
}


#[allow(unused_imports)]
use std::cmp::{max, min};
use std::io::{stdin, stdout, BufWriter, Write};

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}
impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scan = Scanner::default();
    let out = &mut BufWriter::new(stdout());
    let t = scan.next::<usize>();

    for _ in 0..t {
        let n = scan.next::<usize>();

        let mut a = (0..n)
            .map(|i| (scan.next::<usize>(), i + 1))
            .collect::<Vec<_>>();

        a.sort();

        if a[0].0 == a[n - 1].0 {
            println!("NO");
        } else {
            println!("YES");
            println!("{} {}", a[0].1, a[n - 1].1);

            for i in 1..n - 1 {
                if a[i].0 != a[0].0 {
                    println!("{} {}", a[i].1, a[0].1);
                } else {
                    println!("{} {}", a[i].1, a[n - 1].1);
                }
            }
        }
    }
}


#![allow(unused, non_snake_case, dead_code, non_upper_case_globals)]
use {
    std::*,
    std::{cmp::*, collections::*, convert::*, iter::*, marker::*, mem::*, ops::*},
};
fn main() {
    let q = read::<usize>();
    for _ in 0..q {
        solve();
    }
}
fn solve() {
    let n: usize = read();
    let mut a = read_vec::<i64>();
    if a.iter().all(|&x| x == a[0]) {
        println!("{}", "NO");
        return;
    }
    println!("{}", "YES");

    let mut b = vec![];
    for (i, &x) in a.iter().enumerate() {
        b.push((x, i));
    }
    b.sort();
    let base = a[0];
    let mut samebase = BTreeSet::new();
    let mut cango = BTreeSet::new();
    for i in 1..n {
        if a[i] == base {
            samebase.insert(i);
        } else {
            println!("{} {}", 1, i + 1);
            cango.insert(i);
        }
    }
    let to = cango.iter().next().unwrap();
    for &x in samebase.iter() {
        println!("{} {}", to + 1, x + 1);
    }

    // let mut uf = UnionFind::new(n);
    // for i in 1..n {
    //     if b[i - 1].0 == b[i].0 {
    //         uf.unite(b[i - 1].1, b[i].1);
    //     }
    // }
    // let mut roots = BTreeSet::new();
    // for i in 0..n {
    //     let r = uf.find(i);
    //     roots.insert(r);
    // }
    // let mut v = roots.iter().cloned().collect::<Vec<_>>();
    // let m = v.len();
    // let mut mp = vec![0; n];
    // let mut ind = 0;
    // for i in 0..n {
    //     let mr = uf.find(i);
    //     if mr == i {
    //         mp[mr] = ind;
    //         ind += 1;
    //     }
    // }

    // let mut used = BTreeSet::new();
    // let mut notUsed = BTreeSet::new();
    // for i in 0..n {
    //     notUsed.insert(i);
    // }
}

static MX: usize = 1010101;
static MOD: i64 = 1000000007;
static INF: i64 = std::i64::MAX >> 1;
pub struct UnionFind {
    par: Vec<usize>,
    rank: Vec<usize>,
    size: Vec<usize>,
}
impl UnionFind {
    pub fn new(n: usize) -> UnionFind {
        let mut vec = vec![0; n];
        for i in 0..n {
            vec[i] = i;
        }
        UnionFind {
            par: vec,
            rank: vec![0; n],
            size: vec![1; n],
        }
    }
    pub fn find(&mut self, x: usize) -> usize {
        if x == self.par[x] {
            x
        } else {
            let par = self.par[x];
            let res = self.find(par);
            self.par[x] = res;
            res
        }
    }
    pub fn same(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }
    pub fn unite(&mut self, a: usize, b: usize) {
        let apar = self.find(a);
        let bpar = self.find(b);
        if apar == bpar {
            return;
        }
        if self.rank[apar] > self.rank[bpar] {
            self.par[bpar] = apar;
            self.size[apar] += self.size[bpar];
        } else {
            self.par[apar] = bpar;
            self.size[bpar] += self.size[apar];
            if self.rank[apar] == self.rank[bpar] {
                self.rank[bpar] += 1;
            }
        }
    }
    pub fn size(&mut self, a: usize) -> usize {
        let p = self.find(a);
        self.size[p]
    }
}
pub fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}
pub fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}
pub fn read_vec2<T: std::str::FromStr>(n: u32) -> Vec<Vec<T>> {
    (0..n).map(|_| read_vec()).collect()
}


// ---------- begin scannner ----------
#[allow(dead_code)]
mod scanner {
    use std::str::FromStr;
    use std::str::SplitWhitespace;
    use std::io::Read;
    use std;
    pub struct Scanner<'a> {
        it: SplitWhitespace<'a>
    }
    impl<'a> Scanner<'a> {
        pub fn new(s: &'a String) -> Scanner<'a> {
            Scanner {
                it: s.split_whitespace()
            }
        }
        pub fn next<T: FromStr>(&mut self) -> T {
            match self.it.next().unwrap().parse::<T>() {
                Ok(v) => v,
                _ => panic!("Scanner error")
            }
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            self.next::<String>().chars().collect()
        }
        pub fn next_vec<T: FromStr>(&mut self, len: usize) -> Vec<T> {
            (0..len).map(|_| self.next()).collect()
        }
    }
    pub fn read_string() -> String {
        let mut s = String::new();
        std::io::stdin().read_to_string(&mut s).unwrap();
        s
    }
}
// ---------- end scannner ----------

use std::io::Write;

fn main() {
    let sc = scanner::read_string();
    let mut sc = scanner::Scanner::new(&sc);
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    run(&mut sc, &mut out);
}

fn run(sc: &mut scanner::Scanner, out: &mut std::io::BufWriter<std::io::StdoutLock>) {
    let t: usize = sc.next();
    for _ in 0..t {
        let n: usize = sc.next();
        let a: Vec<usize> = sc.next_vec(n);
        let mut map = std::collections::BTreeMap::new();
        for (i, a) in a.iter().enumerate() {
            map.entry(*a).or_insert(vec![]).push(i + 1);
        }
        if map.len() == 1 {
            writeln!(out, "NO").ok();
            continue;
        }
        let a = map.into_iter().map(|a| a.1).collect::<Vec<_>>();
        let v = a[0][0];
        let mut ans = vec![];
        for i in 1..a.len() {
            for a in a[i].iter() {
                ans.push((v, *a));
            }
        }
        let v = a[1][0];
        for a in a[0].iter().skip(1) {
            ans.push((*a, v));
        }
        writeln!(out, "YES").ok();
        for (a, b) in ans {
            writeln!(out, "{} {}", a, b).ok();
        }
    }
}


#![allow(unused_imports)]
#![allow(unused_macros)]

use std::cmp::{
    max, min, Ordering,
    Ordering::{Equal, Greater, Less},
    Reverse,
};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::convert::TryInto;
use std::fmt;
use std::io::{self, Read as _};
use std::mem::swap;
use std::num::{NonZeroU32, ParseIntError};
use std::ops::{
    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
    Index, IndexMut, Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
    SubAssign,
};
use std::process::exit;
use std::{f32, f64, i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize};

pub use visualize::*;
pub mod visualize {
    pub trait Visualize {
        fn visualize(&self, split: &str);
        fn continuous(&self) {
            self.visualize("");
        }
        fn spaces(&self) {
            self.visualize(" ");
        }
        fn lines(&self) {
            self.visualize("\n");
        }
    }
    macro_rules ! impl_vis_for_sized {($ ($ t : ty ) ,+ ) => {$ (impl Visualize for $ t {fn visualize (& self , _split : & str ) {print ! ("{}" , self ) ; } } ) + } ; }
    impl_vis_for_sized! {usize , u8 , u16 , u32 , u64 , u128 , isize , i8 , i16 , i32 , i64 , i128 , String , & str , char }
    impl<T: std::fmt::Display> Visualize for [T] {
        fn visualize(&self, split: &str) {
            let n = self.iter().count();
            print!("{}", {
                let mut buf = String::new();
                for i in 0..n {
                    buf += self[i].to_string().as_str();
                    if i != n - 1 {
                        buf += split;
                    }
                }
                buf
            })
        }
    }
    #[macro_export]
    macro_rules ! vis {() => {println ! () ; } ; ($ last : expr ; ) => {$ last . lines () ; vis ! () } ; ($ last : expr => ) => {$ last . continuous () ; vis ! () ; } ; ($ last : expr $ (, ) ? ) => {$ last . spaces () ; vis ! () ; } ; ($ first : expr ; $ ($ rest : tt ) * ) => {$ first . lines () ; println ! () ; vis ! ($ ($ rest ) * ) ; } ; ($ first : expr => $ ($ rest : tt ) * ) => {$ first . continuous () ; vis ! ($ ($ rest ) * ) ; } ; ($ first : expr , $ ($ rest : tt ) * ) => {$ first . spaces () ; print ! (" " ) ; vis ! ($ ($ rest ) * ) ; } ; }
}

pub use consts::*;
pub mod consts {
    pub const MOD10E9_7: usize = 1000000007; // 10 ^ 9 + 7
    pub const MOD99_: usize = 998244353;
    pub const MAX: u64 = std::u64::MAX; // = 2 ^ 64 - 1 = 18446744073709551615 ≈ 1.8 * 10 ^ 19
    pub const INF: u64 = 2000000000000000000; // MAX / 9 < 2 * 10e18 < MAX / 10
    pub const FNI: i64 = -2000000000000000000; // == -(INF as i64)
    pub const PI: f64 = std::f64::consts::PI; // 3.141592653589793 -- 10 ^ -15
    pub const ASCII_A_LARGE: u8 = 65;
    pub const ASCII_A_SMALL: u8 = 97;
    pub const ASCII_0: u8 = 48;
    pub const ADJ4: &[(isize, isize); 4] = &[(1, 0), (0, 1), (-1, 0), (0, -1)];
    pub const ADJ8: &[(isize, isize); 8] = &[
        (1, 0),
        (1, 1),
        (0, 1),
        (-1, 1),
        (-1, 0),
        (-1, -1),
        (0, -1),
        (1, -1),
    ];
}

fn main() {
    let mut input = "".to_owned();
    io::stdin().read_to_string(&mut input).unwrap();
    let input = input.trim();
    let mut input = input.split_whitespace();

    // generate testcases
    for t in 0..input.next().unwrap().parse::<usize>().unwrap() {
        solve(&mut input);
    }
    // not testcase
    // solve(&mut input);
}

fn solve(input: &mut std::str::SplitWhitespace) {
    macro_rules! read {
        () => ();
        ([$tt:tt]) => (read!([$tt; read!(usize)]));
        ([$tt:tt; $n:expr]) => ((0..$n).map(|_| read!($tt)).collect::<Vec<_>>());
        (($($tt:tt),+)) => (($(read!($tt)),*));
        (Usize1) => (read!(usize) - 1);
        (Chars) => (read!(String).chars().collect::<Vec<char>>());
        (Byte) => (read!(char) as u8);
        (Bytes) => (read!(String).into_bytes());
        ($ty:ty) => (input.next().unwrap().trim().parse::<$ty>().unwrap());
    }
    macro_rules! input {
        ($($id:ident : $ty:tt),*) => {
            $(
                let $id = read!($ty);
            )*
        }
    }

    input! {
        n: usize,
        a: [usize; n]
    }

    let mut a = a
        .into_iter()
        .enumerate()
        .map(|x| (x.1, x.0))
        .collect::<Vec<_>>();
    a.sort_by_key(|x| x.0);
    if a[0].0 == a[n - 1].0 {
        vis!("NO");
    } else {
        vis!("YES");

        // (gang, nth-town);
        let mut first = a[0];
        let mut second = a[n - 1];
        vis!(first.1 + 1, second.1 + 1);
        for &(g, i) in a.iter().skip(1).take(n - 2) {
            // let i = i +;
            // dbg!(first, second, (g, i));
            // assert_ne!(first.0, second.0);
            if g != first.0 {
                vis!(first.1 + 1, i + 1);
                second = (g, i);
            } else if g != second.0 {
                vis!(second.1 + 1, i + 1);
                first = (g, i);
            }
        }
    }
}


#![allow(unused_imports)]
#![allow(unused_macros)]

use std::cmp::{
    max, min, Ordering,
    Ordering::{Equal, Greater, Less},
    Reverse,
};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::convert::TryInto;
use std::fmt;
use std::io::{self, Read as _};
use std::mem::swap;
use std::num::{NonZeroU32, ParseIntError};
use std::ops::{
    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
    Index, IndexMut, Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
    SubAssign,
};
use std::process::exit;
use std::{f32, f64, i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize};

pub use visualize::*;
pub mod visualize {
    pub trait Visualize {
        fn visualize(&self, split: &str);
        fn continuous(&self) {
            self.visualize("");
        }
        fn spaces(&self) {
            self.visualize(" ");
        }
        fn lines(&self) {
            self.visualize("\n");
        }
    }
    macro_rules ! impl_vis_for_sized {($ ($ t : ty ) ,+ ) => {$ (impl Visualize for $ t {fn visualize (& self , _split : & str ) {print ! ("{}" , self ) ; } } ) + } ; }
    impl_vis_for_sized! {usize , u8 , u16 , u32 , u64 , u128 , isize , i8 , i16 , i32 , i64 , i128 , String , & str , char }
    impl<T: std::fmt::Display> Visualize for [T] {
        fn visualize(&self, split: &str) {
            let n = self.iter().count();
            print!("{}", {
                let mut buf = String::new();
                for i in 0..n {
                    buf += self[i].to_string().as_str();
                    if i != n - 1 {
                        buf += split;
                    }
                }
                buf
            })
        }
    }
    #[macro_export]
    macro_rules ! vis {() => {println ! () ; } ; ($ last : expr ; ) => {$ last . lines () ; vis ! () } ; ($ last : expr => ) => {$ last . continuous () ; vis ! () ; } ; ($ last : expr $ (, ) ? ) => {$ last . spaces () ; vis ! () ; } ; ($ first : expr ; $ ($ rest : tt ) * ) => {$ first . lines () ; println ! () ; vis ! ($ ($ rest ) * ) ; } ; ($ first : expr => $ ($ rest : tt ) * ) => {$ first . continuous () ; vis ! ($ ($ rest ) * ) ; } ; ($ first : expr , $ ($ rest : tt ) * ) => {$ first . spaces () ; print ! (" " ) ; vis ! ($ ($ rest ) * ) ; } ; }
}

pub use consts::*;
pub mod consts {
    pub const MOD10E9_7: usize = 1000000007; // 10 ^ 9 + 7
    pub const MOD99_: usize = 998244353;
    pub const MAX: u64 = std::u64::MAX; // = 2 ^ 64 - 1 = 18446744073709551615 ≈ 1.8 * 10 ^ 19
    pub const INF: u64 = 2000000000000000000; // MAX / 9 < 2 * 10e18 < MAX / 10
    pub const FNI: i64 = -2000000000000000000; // == -(INF as i64)
    pub const PI: f64 = std::f64::consts::PI; // 3.141592653589793 -- 10 ^ -15
    pub const ASCII_A_LARGE: u8 = 65;
    pub const ASCII_A_SMALL: u8 = 97;
    pub const ASCII_0: u8 = 48;
    pub const ADJ4: &[(isize, isize); 4] = &[(1, 0), (0, 1), (-1, 0), (0, -1)];
    pub const ADJ8: &[(isize, isize); 8] = &[
        (1, 0),
        (1, 1),
        (0, 1),
        (-1, 1),
        (-1, 0),
        (-1, -1),
        (0, -1),
        (1, -1),
    ];
}

fn main() {
    let mut input = "".to_owned();
    io::stdin().read_to_string(&mut input).unwrap();
    let input = input.trim();
    let mut input = input.split_whitespace();

    // generate testcases
    for t in 0..input.next().unwrap().parse::<usize>().unwrap() {
        solve(&mut input);
    }
    // not testcase
    // solve(&mut input);
}

fn solve(input: &mut std::str::SplitWhitespace) {
    macro_rules! read {
        () => ();
        ([$tt:tt]) => (read!([$tt; read!(usize)]));
        ([$tt:tt; $n:expr]) => ((0..$n).map(|_| read!($tt)).collect::<Vec<_>>());
        (($($tt:tt),+)) => (($(read!($tt)),*));
        (Usize1) => (read!(usize) - 1);
        (Chars) => (read!(String).chars().collect::<Vec<char>>());
        (Byte) => (read!(char) as u8);
        (Bytes) => (read!(String).into_bytes());
        ($ty:ty) => (input.next().unwrap().trim().parse::<$ty>().unwrap());
    }
    macro_rules! input {
        ($($id:ident : $ty:tt),*) => {
            $(
                let $id = read!($ty);
            )*
        }
    }

    input! {
        n: usize,
        a: [usize; n]
    }

    let mut a = a
        .into_iter()
        .enumerate()
        .map(|x| (x.1, x.0))
        .collect::<Vec<_>>();
    a.sort_by_key(|x| x.1);
    if a[0].0 == a[n - 1].0 {
        vis!("NO");
    } else {
        vis!("YES");
        let mut first = a[0];
        let mut second = a[n - 1];
        vis!(first.1 + 1, second.1 + 1);
        for &(g, i) in a.iter().skip(1).take(n - 2) {
            // let i = i +;
            // dbg!(first, second, (g, i));
            // assert_ne!(first.0, second.0);
            if g != first.0 {
                vis!(first.1 + 1, i + 1);
                second = (g, i);
            } else if g != second.0 {
                vis!(second.1 + 1, i + 1);
                first = (g, i);
            }
        }
    }
}