跳转至

我就说这个题绝对见过

![[Pasted image 20260211231523.png]]

B. Array and Permutation

时间限制:每个测试点1.5秒
内存限制:每个测试点256兆字节

问题描述

给定一个长度为 n∗ 的排列 p 和一个长度为 n 的数组 a

如果可以通过执行若干次(可能为零次)以下类型的操作从排列 p 得到数组 a,则称排列 p 是数组 a生成排列

选择一个下标 i1 \le i < n),并执行以下两种替换之一: - p_i := p_{i+1}; - p_{i+1} := p_i

换句话说,在一次操作中,你可以选择数组中两个相邻的元素,并将其中一个元素的值复制到另一个元素中。

你需要判断排列 p 是否为数组 a 的生成排列。

∗ 长度为 n 的排列是由 n 个从 1n 的不同整数按任意顺序组成的数组。例如,[2,3,1,5,4] 是一个排列,但 [1,2,2] 不是排列(2 在数组中出现两次),[1,3,4] 也不是排列(n=3 但数组中含有 4)。

输入格式

每个测试包含多个测试用例。第一行包含一个整数 t,表示测试用例的数量(1 \le t \le 10^4)。
接下来是每个测试用例的描述。

每个测试用例的第一行包含一个整数 n2 \le n \le 2 \times 10^5)——数组和排列的长度。

第二行包含 n 个整数 p_1, p_2, \ldots, p_n1 \le p_i \le n)——排列 p 的元素。

第三行包含 n 个整数 a_1, a_2, \ldots, a_n1 \le a_i \le n)——数组 a 的元素。

保证所有测试用例中 n 的总和不超过 2 \times 10^5

输出格式

对于每个测试用例,如果排列 p 是数组 a 的生成排列,则输出 "YES",否则输出 "NO"

每个字母的大小写不限(小写或大写均可)。例如,字符串 "yEs""yes""Yes""YES" 都将被接受为肯定答案。

样例输入

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

样例输出

YES
NO
YES
NO
YES
YES

样例说明

在第一个测试用例中,通过一次操作即可从排列生成数组:

i = 2,执行 p_{i+1} := p_i

在第二个测试用例中,无法从 p 得到 a

在第三个测试用例中,需要执行两次操作:

i = 1,执行 p_i := p_{i+1}
i = 2,执行 p_{i+1} := p_i

AC 代码

// Problem: CF 2197 B
// Contest: Codeforces - Codeforces Round 1079 (Div. 2)
// URL: https://codeforces.com/contest/2197/problem/B
// Memory Limit: 256 MB
// Time Limit: 1500 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<bits/stdc++.h>
using namespace std;

void solve(){
    int n;
    cin>>n;
    vector<int> p(n),a(n),re(n+3);

    for(int i=0;i<n;i++){
        cin>>p[i];
        re[p[i]]=i;
    }

    vector<int> ans;
    for(int i=0;i<n;i++){
        cin>>a[i];
        ans.push_back(re[a[i]]);
        //cout<<re[a[i]]<<" ";
    }

    for(int i=1;i<n;i++){
        if(ans[i]<ans[i-1])
        {
            cout<<"NO"<<endl;
            return ;
        }
    }
    cout<<"YES"<<endl;
    return ;
}


int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
    return 0;
}