You are given an array a_1, a_2, ..., a_n and an array b_1, b_2, ..., b_n.

For one operation you can sort in non-decreasing order any subarray a[l ... r] of the array a.

For example, if a = [4, 2, 2, 1, 3, 1] and you choose subbarray a[2 ... 5], then the array turns into [4, 1, 2, 2, 3, 1]. 

You are asked to determine whether it is possible to obtain the array b by applying this operation any number of times (possibly zero) to the array a.

Input

The first line contains one integer t (1 ≤ t ≤ 3 ⋅ 10^5) — the number of queries.

The first line of each query contains one integer n (1 ≤ n ≤ 3 ⋅ 10^5).

The second line of each query contains n integers a_1, a_2, ..., a_n (1 ≤ a_i ≤ n).

The third line of each query contains n integers b_1, b_2, ..., b_n (1 ≤ b_i ≤ n).

It is guaranteed that ∑ n ≤ 3 ⋅ 10^5 over all queries in a test.

Output

For each query print YES (in any letter case) if it is possible to obtain an array b and NO (in any letter case) otherwise.

Example

Input


4
7
1 7 1 4 4 5 6
1 1 4 4 5 7 6
5
1 1 3 3 5
1 1 3 3 5
2
1 1
1 2
3
1 2 3
3 2 1


Output


YES
YES
NO
NO

Note

In first test case the can sort subarray a_1 ... a_5, then a will turn into [1, 1, 4, 4, 7, 5, 6], and then sort subarray a_5 ... a_6.
import java.util.*;

public class CF1187D {


    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < t; i++){
            sb.append(check(sc)).append(" ");
        }
        System.out.println(sb.toString());
    }

    private static String check(Scanner sc){
        int n = sc.nextInt();

        int[] a = new int[n];
        int[] b = new int[n];

        // 记录数组a，并将数据放入一个map中，结构为：值 -> [ 位置1，位置2，位置3... ]
        Map<Integer, Queue<Integer>> aMap = new HashMap<>();
        for(int i = 0; i < n; i++){
            a[i] = sc.nextInt();

            if(aMap.containsKey(a[i])){
                aMap.get(a[i]).add(i);
            }else{
                Queue<Integer> queue = new LinkedList<>();
                queue.add(i);
                aMap.put(a[i], queue);
            }
        }

        // 记录数组b
        for(int i = 0; i < n; i++){
            b[i] = sc.nextInt();
        }

        // 构造a的线段树
        CF1187D cf1187D = new CF1187D();
        Line aTree = cf1187D.buildLineTree(a);

        //从左到右循环数组b
        for(int i = 0; i < n; i++){
            int v = b[i];

            // 在a中找不到对应的值，返回"NO"
            if(!aMap.containsKey(v)){
                return "NO";
            } else if(aMap.get(v) == null || aMap.get(v).size() == 0){
                return "NO";
            }

            // 对于b[i]，找到数组a中，相同值的第一个元素位置j
            int j = aMap.get(v).poll();

            // 在a的线段树中查询，0 到 j 之间的最小值
            int a_min = cf1187D.searchMin(aTree, 0, j);
            if(a_min != v){
                //对于数组a，如果在 i 到 j之间，有比 a[j] 还小的数，则无法通过排序使得a[j]向前移动到位置i
                return "NO";
            }else{
                // 如果满足条件：a[j] 是 0 到 j的最小值
                // 则意味着，a[j]可以通过不断和前一个数排序，移动到位置i上，使其和b[i]匹配，且保持其他数据的顺序不变
                // 但是数组的位置移动是copy操作，性能差，无法满足题目的要求
                // 可以采取高效的等价操作：将a[j]位置"抹去"，使其在下次取线段最小值的时候，不产生干扰，而其他数据的顺序不变
                // "抹去"的做法是将该值更新为一个操作300000的最大值
                cf1187D.updateMin(aTree, j, Integer.MAX_VALUE);
            }
        }

        return "YES";
    }

    /**
     * 线段树
     */
    class Line {
        private Line left_child;        //左边的子节点
        private Line right_child;       //右边的子节点
        private int min;                //线段中的最小值
        private int left;               //线段的起始位置
        private int right;              //线段的结束位置


        public Line(int left, int right, int min){
            this.left = left;
            this.right = right;
            this.min = min;
        }

    }

    /**
     * 根据数组构造线段树
     * @param a
     * @return
     */
    public Line buildLineTree(int[] a){
        return buildLine(0, a.length - 1, a);
    }

    /**
     * 根据数组中的起始和结束位置，构造线段（树）
     * @param left      起始位置
     * @param right     结束位置
     * @param a         数组
     * @return
     */
    public Line buildLine(int left, int right, int[] a){
        Line root = new Line(left, right, a[left]);
        if(left == right){
            return root;
        }
        int mid = (left + right) / 2;
        root.left_child = buildLine(left, mid, a);
        root.right_child = buildLine(mid + 1, right, a);
        root.min = Math.min(root.left_child.min, root.right_child.min);
        return root;
    }

    /**
     * 查询线段树下，某个线段中的最小值
     * @param root      线段树
     * @param left      起始位置
     * @param right     结束位置
     * @return
     */
    private int searchMin(Line root, int left, int right){
        if(root.left == left && root.right == right){
            return root.min;
        }
        int mid = (root.left + root.right) / 2;

        if(left >= mid + 1){
            return searchMin(root.right_child, left, right);
        }else if(right <= mid){
            return searchMin(root.left_child, left, right);
        }else{
            return Math.min(searchMin(root.left_child, left, mid), searchMin(root.right_child, mid + 1, right));
        }
    }

    /**
     * 更新线段中的某个位置的值，以及同时更新受影响的线段的最小值
     * @param root      线段树
     * @param index     更新位置
     * @param value     更新值
     */
    private void updateMin(Line root, int index, int value){
        if(root.left == index && root.right == index){
            root.min = value;
            return;
        }

        int mid = (root.left + root.right) / 2;
        if(index >= mid + 1){
            updateMin(root.right_child, index, value);
        }else{
            updateMin(root.left_child, index, value);
        }
        root.min = Math.min(root.left_child.min, root.right_child.min);
    }
}

