思路:
线段树好题。对a数组中的每个元素从左到右依次操作,判断最终是否能够转化成b数组。在此过程中使用线段树维护区间最小值判断是否能够进行合法操作。
实现:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 300005, INF = 0x3f3f3f3f; 4 deque<int> d[N]; 5 int a[N], b[N], tree[N * 4]; 6 7 void build(int num, int l, int r) 8 { 9 if (l == r) { tree[num] = a[l]; return; } 10 int m = l + r >> 1; 11 build(num << 1, l, m); 12 build(num << 1 | 1, m + 1, r); 13 tree[num] = min(tree[num << 1], tree[num << 1 | 1]); 14 } 15 16 void update(int num, int l, int r, int x, int y) 17 { 18 if (l == r) { tree[num] = y; return; } 19 int m = l + r >> 1; 20 if (x <= m) update(num << 1, l, m, x, y); 21 else update(num << 1 | 1, m + 1, r, x, y); 22 tree[num] = min(tree[num << 1], tree[num << 1 | 1]); 23 } 24 25 int query(int num, int l, int r, int x, int y) 26 { 27 if (x <= l && y >= r) return tree[num]; 28 int m = l + r >> 1; 29 int ans = INF; 30 if (x <= m) ans = min(ans, query(num << 1, l, m, x, y)); 31 if (y >= m + 1) ans = min(ans, query(num << 1 | 1, m + 1, r, x, y)); 32 return ans; 33 } 34 35 int main() 36 { 37 int t, n; cin >> t; 38 while (t--) 39 { 40 cin >> n; 41 for (int i = 1; i <= n; i++) d[i].clear(); 42 for (int i = 1; i <= n; i++) { cin >> a[i]; d[a[i]].push_back(i); } 43 build(1, 1, n); 44 for (int i = 1; i <= n; i++) cin >> b[i]; 45 bool flg = true; 46 int i = 1, j = 1; 47 while (i <= n && j <= n) 48 { 49 while (i <= n && a[i] == INF) i++; 50 if (a[i] == b[j]) { d[a[i]].pop_front(); i++; j++; } 51 else if (a[i] < b[j]) { flg = false; break; } 52 else 53 { 54 if (d[b[j]].empty()) { flg = false; break; } 55 else 56 { 57 int t = d[b[j]].front(); 58 int minn = query(1, 1, n, i, t); 59 if (minn < a[t]) { flg = false; break; } 60 else 61 { 62 update(1, 1, n, t, INF); a[t] = INF; 63 d[b[j]].pop_front(); 64 j++; 65 } 66 } 67 } 68 } 69 cout << (flg ? "YES" : "NO") << endl; 70 } 71 return 0; 72 }