Educational Codeforces Round 67 D. Subarray Sorting

Educational Codeforces Round 67 D. Subarray Sorting

传送门

题意;

给出两个数组(a,b),现在可以对(a)数组进行任意次排序,问最后能否得到(b)数组。
(nleq 3*10^5,aleq n.)

思路:

首先注意到任意次排序可以等价于任意次交换两个相邻的数,当且仅当前一个数不小于后面一个数。
我一开始想的是按权值从小到大来构造,但最终发现这条路走不通。
正解就是比较直接的思路,按位置一个一个来匹配。
对于一个(b_i),询问目前出现位置最早的(a_j),满足(a_j=b_i),当其能够移动过去,只要前面的数权值都不小于(a_j)即可。
因为我们匹配过后就要把(a_j)删去并且重新更新,所以不会出现(j<i)的情况。
以上权值线段树维护最小位置+vector存储位置即可解决。
代码如下:

#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 3e5 + 5;
int T;
int n;
int a[N], b[N];
vector <int> p[N];
int Min[N << 2];
void build(int o, int l, int r) {
    Min[o] = INF;
    if(l == r) return ;
    int mid = (l + r) >> 1;
    build(o << 1, l, mid);
    build(o << 1|1, mid + 1, r);
}
void update(int o, int l, int r, int p, int v) {
    if(l == r) {
        Min[o] = v;
        return ;
    }
    int mid = (l + r) >> 1;
    if(p <= mid) update(o << 1, l, mid, p, v);
    else update(o << 1|1, mid + 1, r, p, v);
    Min[o] = min(Min[o << 1], Min[o << 1|1]);
}
int query(int o, int l, int r, int L, int R) {
    if(l >= L && r <= R) return Min[o];
    int ans = INF;
    int mid = (l + r) >> 1;
    if(L <= mid) ans = min(ans, query(o << 1, l, mid, L, R));
    if(R > mid) ans = min(ans, query(o << 1|1, mid + 1, r, L, R));
    return ans;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> T;
    while(T--) {
        cin >> n;
        for(int i = 1; i <= n; i++) p[i].clear();
        for(int i = 1; i <= n; i++) {
            cin >> a[i];
            p[a[i]].push_back(i);
        }
        for(int i = 1; i <= n; i++) cin >> b[i];
        build(1, 1, n);
        for(int i = 1; i <= n; i++) if(!p[i].empty()) {
            reverse(p[i].begin(), p[i].end());
            update(1, 1, n, i, p[i].back());
        }
        bool ok = true;
        for(int i = 1; i <= n; i++) {
            if(p[b[i]].empty()) {
                ok = false;
                break;
            }
            if(query(1, 1, n, 1, b[i]) < p[b[i]].back()) {
                ok = false;
                break;
            }
            p[b[i]].pop_back();
            update(1, 1, n, b[i], (p[b[i]].empty() ? INF : p[b[i]].back()));
        }
        if(ok) cout << "YES" << '
';
        else cout << "NO" << '
';
    }
    return 0;
}

原文地址:https://www.cnblogs.com/heyuhhh/p/11313784.html