Hackforces…
D:
题意是可以进行任意次操作,每次操作将一个子数组进行排序。问能否将数组a变为数组b。
通过交换相邻两个元素(当前一个大于后一个)使得一个子数组有序是冒泡排序的算法。
这就是说题目中的每一次操作可以看成若干次交换相邻两次元素的操作,且交换相邻两个元素是满足题目操作的要求的。因此问题转化为每次操作是排序一个长度为2的子数组。
那么对b从左到右遍历。对于一个元素
b
1
b_1
b1 ,我们找出最小的
j
j
j 满足
b
1
=
a
j
b_1=a_j
b1=aj ,且
a
j
a_j
aj 前面的所有数大于
a
j
a_j
aj 。找不到就输出NO。如果找得到就删去
b
1
b_1
b1 和
a
j
a_j
aj 。继续处理。
#include <bits/stdc++.h>
#define lson (rt<<1)
#define rson (rt<<1|1)
using namespace std;
const int N = 3e5+7;
int a[N], b[N];
map<int, stack<int>> st;
int mn[N<<2];
void build(int rt, int l, int r) {
if(l==r) {
mn[rt]=a[l];
return;
}
int m = (l+r)>>1;
build(lson, l, m);
build(rson, m+1, r);
mn[rt] = min(mn[lson], mn[rson]);
}
void update(int rt, int l, int r, int p) {
if(l==r) {
mn[rt]=N;
return;
}
int m = (l+r)>>1;
if(p<=m) update(lson, l, m, p);
else update(rson, m+1, r, p);
mn[rt] = min(mn[lson], mn[rson]);
}
int query(int rt, int l, int r, int ql, int qr) {
if(ql<=l&&qr>=r) {
return mn[rt];
}
int m = (l+r)>>1;
int res = N;
if(ql<=m) res = min(res, query(lson, l, m, ql, qr));
if(qr>m) res = min(res, query(rson, m+1, r, ql, qr));
return res;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
int n;
scanf("%d", &n);
st.clear();
for(int i=1; i<=n; ++i) scanf("%d", &a[i]);
for(int i=1; i<=n; ++i) scanf("%d", &b[i]);
build(1, 1, n);
for(int i=n; i>=1; --i) {
st[a[i]].push(i);
}
bool ok = true;
for(int i=1; i<=n; ++i) {
// printf("I: %d\n", i);
if(st[b[i]].empty()) {
ok = false;
break;
}
int k = st[b[i]].top();
st[b[i]].pop();
// printf("k: %d\n", k);
int p = (k==1?N:query(1, 1, n, 1, k-1));
// if(k!=1) printf("udp %d, query: %d, p: %d\n", k, query(1, 1, n, 1, k-1), p);
// k==1 肯定可以, p==-1表示前面没其他值
if(p>b[i]||p==N) {
update(1, 1, n, k);
} else {
ok = false;
break;
}
}
if(ok) puts("YES");
else puts("NO");
}
return 0;
}