0%

CF-1079-B. Array and Permutation

题目大意

给定一个长度为 nn 的排列 pp 和一个长度为 nn 的数组 aa

你可以进行任意次操作,每次操作选择一个下标 ii1i<n1 \le i < n),然后执行以下两种之一:

  • pip_i 的值覆盖为 pi+1p_{i+1}(即 pi:=pi+1p_i := p_{i+1}

  • pi+1p_{i+1} 的值覆盖为 pip_i(即 pi+1:=pip_{i+1} := p_i

也就是说,每次选两个相邻元素,把其中一个的值复制到另一个上。

判断是否能通过若干次操作,把排列 pp 变成数组 aa

样例解释:

第一组:p=[1,2,3]p = [1, 2, 3]a=[1,2,2]a = [1, 2, 2]。选 i=2i = 2,把 p2p_2 的值复制到 p3p_3,得到 [1,2,2][1, 2, 2],与 aa 相同,输出 YES

第二组:p=[3,1,2,4]p = [3, 1, 2, 4]a=[3,4,2,2]a = [3, 4, 2, 2],无论如何操作都无法得到 aa,输出 NO

第三组:p=[1,3,2,5,4]p = [1, 3, 2, 5, 4]a=[3,3,3,5,4]a = [3, 3, 3, 5, 4]。先选 i=1i = 1,把 p2p_2 的值复制到 p1p_1,得到 [3,3,2,5,4][3, 3, 2, 5, 4];再选 i=2i = 2,把 p2p_2 的值复制到 p3p_3,得到 [3,3,3,5,4][3, 3, 3, 5, 4],与 aa 相同,输出 YES

思路讲解

使用类似于双指针的做法,判断这个 A 数组是去重以后是否是 P 数组 P 排列的子序列。具体来说,在实现当中,我们是使用 P 排列去对应 A 的这个数组,去对应 A 数组,就是你可以理解为我们用一个 PI 去消 AJ 去消 A 数组中的元素,那么这个 pi 当然是可以一直消一直消,可以消除连续的 aj 的元素,只要 aj 和 pi 相等,连续的相等就可以。但是 pi 一旦遇到了第一个和自己不相等的 aj 就会停下来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void Solve() {
ll N;
cin >> N;
vector<ll> P(N+2),A(N+2);
for (int i=1;i<=N;++i) {
cin>>P[i];
}
for (int i=1;i<=N;++i) {
cin>>A[i];
}
ll bp=1;
for (ll i=1;i<=N;++i) {
bool isbreak=false;
for (ll j=bp;j<=N;++j) {
if (P[i]!=A[j]) {
bp=j;
isbreak=true;
break;
}
}
if (!isbreak) {
bp=N+1;
}
}
if (bp==N+1) {
cout<<"YES\n";
}else {
cout<<"NO\n";
}
}

AC代码

AC
https://codeforces.com/contest/2197/submission/362443575

心路历程(WA,TLE,MLE……)