• 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;
    }
    
    
  • 相关阅读:
    Hammer.js 实现移动端库事件
    使用两个队列模拟一个栈
    选择排序算法
    插入排序算法
    找出一个整形数组中第二大的数字
    双向冒泡排序算法
    求一个整形数组的最大子数组之和
    循环删除数组中元素的问题
    关于如何输出if()..else里的内容的问题
    小米2017秋招真题——电话号码分身问题(Java版)
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11313784.html
Copyright © 2020-2023  润新知