Problem: You are given an array a consisting of n integers.

Let min(l, r) be the minimum value among a_l, a_{l + 1}, …, a_r and max(l, r) be the maximum value among a_l, a_{l + 1}, …, a_r.

Your task is to choose three positive (greater than 0) integers x, y and z such that:

  * x + y + z = n; 
  * max(1, x) = min(x + 1, x + y) = max(x + y + 1, n). 



In other words, you have to split the array a into three consecutive non-empty parts that cover the whole array and the maximum in the first part equals the minimum in the second part and equals the maximum in the third part (or determine it is impossible to find such a partition).

Among all such triples (partitions), you can choose any.

You have to answer t independent test cases.

Input

The first line of the input contains one integer t (1 ≤ t ≤ 2 ⋅ 10^4) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (3 ≤ n ≤ 2 ⋅ 10^5) — the length of a.

The second line of the test case contains n integers a_1, a_2, …, a_n (1 ≤ a_i ≤ 10^9), where a_i is the i-th element of a.

It is guaranteed that the sum of n does not exceed 2 ⋅ 10^5 (∑ n ≤ 2 ⋅ 10^5).

Output

For each test case, print the answer: NO in the only line if there is no such partition of a that satisfies the conditions from the problem statement. Otherwise, print YES in the first line and three integers x, y and z (x + y + z = n) in the second line.

If there are several answers, you can print any.

Example

Input


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


Output


YES
6 1 4
NO
YES
2 5 2
YES
4 1 2
YES
1 1 3
YES
2 1 4

Solution (in JAVA):

Solution:
import java.util.*;
import java.io.*;
import static java.lang.Math.*;
public class test {
    final static int MOD = 1000000007;
    final static int intMax = 1000000000;
    final static int intMin = -1000000000;
    final static int[] dx = { 0, 0, -1, 1 };
    final static int[] dy = { -1, 1, 0, 0 };

    static int add(int a, int b) {
        return (a + b) % MOD;
    }

    static int sub(int a, int b) {
        return (a - b + MOD) % MOD;
    }

    static int mult(int a, int b) {
        return (int)((((long)(a)) * b) % MOD);
    }

    static class Reader {
        final private int BUFFER_SIZE = 1 << 16;
        private DataInputStream din;
        private byte[] buffer;
        private int bufferPointer, bytesRead;

        public Reader() {
            din = new DataInputStream(System.in);
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public Reader(String file_name) throws IOException {
            din = new DataInputStream(new FileInputStream(file_name));
            buffer = new byte[BUFFER_SIZE];
            bufferPointer = bytesRead = 0;
        }

        public String readLine() throws IOException {
            byte[] buf = new byte[360]; // line length
            int cnt = 0, c;
            while ((c = read()) != -1) {
                if (c == '\n')
                    break;
                buf[cnt++] = (byte) c;
            }
            return new String(buf, 0, cnt);
        }

        public int nextInt() throws IOException {
            int ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');

            if (neg)
                return -ret;
            return ret;
        }

        public long nextLong() throws IOException {
            long ret = 0;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();
            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');
            if (neg)
                return -ret;
            return ret;
        }

        public double nextDouble() throws IOException {
            double ret = 0, div = 1;
            byte c = read();
            while (c <= ' ')
                c = read();
            boolean neg = (c == '-');
            if (neg)
                c = read();

            do {
                ret = ret * 10 + c - '0';
            } while ((c = read()) >= '0' && c <= '9');

            if (c == '.') {
                while ((c = read()) >= '0' && c <= '9') {
                    ret += (c - '0') / (div *= 10);
                }
            }

            if (neg)
                return -ret;
            return ret;
        }

        private void fillBuffer() throws IOException {
            bytesRead = din.read(buffer, bufferPointer = 0, BUFFER_SIZE);
            if (bytesRead == -1)
                buffer[0] = -1;
        }

        private byte read() throws IOException {
            if (bufferPointer == bytesRead)
                fillBuffer();
            return buffer[bufferPointer++];
        }

        public void close() throws IOException {
            if (din == null)
                return;
            din.close();
        }
    }

    static class Sb_Output implements Closeable, Flushable{
        StringBuilder sb;
        OutputStream os;
        int BUFFER_SIZE;
        public Sb_Output(String s) throws Exception {
            os = new BufferedOutputStream(new FileOutputStream(new File(s)));
            BUFFER_SIZE = 1 << 16;
            sb = new StringBuilder(BUFFER_SIZE);
        }
        public void print(String s) {
            sb.append(s);
            if(sb.length() >= (BUFFER_SIZE>>1)) {
                flush();
            }
        }
        public void println(String s) {
            print(s);
            print("\n");
        }
        public void println(int i) {
            println("" + i);
        }
        public void println(long i) {
            println("" + i);
        }
        public void flush() {
            try {
                os.write(sb.toString().getBytes());
                sb = new StringBuilder(BUFFER_SIZE);
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
        public void close() {
            flush();
            try {
                os.close();
            }catch(IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Reader in = new Reader();
//		Reader in = new Reader("poetry.in");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//        BufferedReader br = new BufferedReader(new FileReader("poetry.in"));
        int t = Integer.parseInt(br.readLine());
        while(t-->0){
            int n = Integer.parseInt(br.readLine());
            int a[] = new int[n];
            StringTokenizer st = new StringTokenizer(br.readLine());
            for(int i = 0; i < n; ++i){
                a[i] = Integer.parseInt(st.nextToken());
            }
            HashMap<Integer, TreeSet<Integer>> inds = new HashMap<Integer, TreeSet<Integer>>();
            for(int i = 0; i < n; ++i){
                if(!inds.containsKey(a[i])) {
                    inds.put(a[i], new TreeSet<Integer>());
                }
                inds.get(a[i]).add(i);
            }
            int[] ans = {-1, -1, -1};
            int mx = 0;
            LazySegmentTree rmq = new LazySegmentTree(n + 1);
            for(int i = 0; i < n; ++i){
                rmq.update(i, i, a[i]);
            }
            for(int i = 0; i < n - 2; ++i){
                mx = max(mx, a[i]);
                inds.get(a[i]).remove(i);
                TreeSet<Integer> cur = inds.get(mx);
                if(cur.size() <= 1) continue;
                int fst = cur.first();
                int lst = cur.last();
                if(rmq.minQuery(i + 1, fst) != mx || rmq.maxQuery(lst, n - 1) != mx) {
                    continue;
                }
                if(fst == lst - 1) {
                    ans[0] = i + 1;
                    ans[1] = fst - i;
                    ans[2] = n - lst;
                    break;
                }
                int l = fst, r = lst - 1;
                while(l < r){
                    int m = l + (r - l + 1) / 2;
                    if(rmq.minQuery(i + 1, m) < mx) {
                        r = m - 1;
                    } else{
                        l = m;
                    }
                }
                if(rmq.maxQuery(l + 1, n - 1) == mx) {
                    ans[0] = i + 1;
                    ans[1] = l - i;
                    ans[2] = n - 1 - l;
                    break;
                }
            }
            if(ans[0] == -1) System.out.println("NO");
            else{
                System.out.println("YES");
                System.out.println(ans[0] + " " + ans[1] + " " + ans[2]);
            }
        }
        in.close();

    }
    static class pair{
        int x, y;
        pair(int a, int b){
            x = a; y = b;
        }
    }
    static class LazySegmentTree {
        private long[] min;
        private long[] lazy;
        private long[] sum;
        private long[] max;
        private int size;
        public LazySegmentTree(int size) {
            this.size = size;
            min = new long[4*size];
            sum = new long[4*size];
            max = new long[4*size];
            lazy = new long[4*size];
        }
        public void update(int l, int r, int inc) {
            update(1, 0, size-1, l, r, inc);
        }
        private void pushDown(int index, int l, int r) {
            min[index] += lazy[index];
            max[index] += lazy[index];
            sum[index] += lazy[index] * (r-l+1);
            if(l != r) {
                lazy[2*index] += lazy[index];
                lazy[2*index+1] += lazy[index];
            }
            lazy[index] = 0;
        }
        private void pullUp(int index, int l, int r) {
            int m = (l+r)/2;
            min[index] = Math.min(evaluateMin(2*index, l, m), evaluateMin(2*index+1, m+1, r));
            max[index] = Math.max(evaluateMax(2*index, l, m), evaluateMax(2*index+1, m+1, r));
            sum[index] = evaluateSum(2*index, l, m) + evaluateSum(2*index+1, m+1, r);
        }
        private long evaluateSum(int index, int l, int r) {
            return sum[index] + (r-l+1)*lazy[index];
        }
        private long evaluateMin(int index, int l, int r) {
            return min[index] + lazy[index];
        }
        private long evaluateMax(int index, int l, int r) {
            return max[index] + lazy[index];
        }
        private void update(int index, int l, int r, int left, int right, int inc) {
            if(r < left || l > right) return;
            if(l >= left && r <= right) {
                lazy[index] += inc;
                return;
            }
            pushDown(index, l, r);
            int m = (l+r)/2;
            update(2*index, l, m, left, right, inc);
            update(2*index+1, m+1, r, left, right, inc);
            pullUp(index, l, r);
        }
        public long minQuery(int l, int r) {
            return minQuery(1, 0, size-1, l, r);
        }
        private long minQuery(int index, int l, int r, int left, int right) {
            if(r < left || l > right) return Long.MAX_VALUE;
            if(l >= left && r <= right) {
                return evaluateMin(index, l, r);
            }
            pushDown(index, l, r);
            int m = (l+r)/2;
            long ret = Long.MAX_VALUE;
            ret = Math.min(ret, minQuery(2*index, l, m, left, right));
            ret = Math.min(ret, minQuery(2*index+1, m+1, r, left, right));
            pullUp(index, l, r);
            return ret;
        }
        public long sumQuery(int l, int r) {
            return sumQuery(1, 0, size-1, l, r);
        }
        private long sumQuery(int index, int l, int r, int left, int right) {
            if(r < left || l > right) return 0;
            if(l >= left && r <= right) {
                return evaluateSum(index, l, r);
            }
            pushDown(index, l, r);
            int m = (l+r)/2;
            long ret = 0;
            ret += sumQuery(2*index, l, m, left, right);
            ret += sumQuery(2*index+1, m+1, r, left, right);
            pullUp(index, l, r);
            return ret;
        }
        public long maxQuery(int l, int r) {
            return maxQuery(1, 0, size-1, l, r);
        }
        private long maxQuery(int index, int l, int r, int left, int right) {
            if(r < left || l > right) return Long.MIN_VALUE;
            if(l >= left && r <= right) {
                return evaluateMax(index, l, r);
            }
            pushDown(index, l, r);
            int m = (l+r)/2;
            long ret = 0;
            ret = Math.max(ret, maxQuery(2*index, l, m, left, right));
            ret = Math.max(ret, maxQuery(2*index+1, m+1, r, left, right));
            pullUp(index, l, r);
            return ret;
        }
    }
}