Codeforces E67 D. Subarray Sorting

题目链接

题目:

给你两个数组a[], b[],对第一个数组你可以选择任意一个区间[l,r]进行从小到大排序。问能不能将a数组经过多次操作变成b数组。

题解:

首先,我们能发现一个数要向前移动,只能前面的数比它大时才可以向前移。所以要想把a变成b相当于用a中的数构造b,扫一遍b对每一位b[i],在a中
找到第一个和b[i]相同的数a[k],要想移到b[i]位置这个a[k]要是从i到j的最小值。
如何快速找到每个a[j]呢?我们可以开n个queue,每个队列保存a[]中数的位置。每次对b[i]取queue[b[i]]的队头,就是位置k,如果我们每次使用一个数后把它从a[]
中删除掉,那只用判断a[k]是1~k的最小值就说明可以用a[k]构造b[i],这个可以用线段树取维护。每次删除相当于在线段树中把这一位设为INF.

代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, n) for(ll i = a; i <= n; ++ i)
#define per(i, a, n) for(ll i = n; i >= a; -- i)
typedef long long ll;
const int N = 3e5 + 105;
const int mod = 998244353;
const double Pi = acos(- 1.0);
const int INF = 0x3f3f3f3f;
const int G = 3, Gi = 332748118;
ll qpow(ll a, ll b) { ll res = 1; while(b){ if(b) res = (res * a) % mod; a = (a * a) % mod; b >>= 1;} return res; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
//

int T, n;
int a[N], b[N];
queue<int>sol[N];

struct Tree{
    int l, r;
    int minval;
}tree[N * 4];

void Pushup(int index){
    tree[index].minval = min(tree[index << 1].minval, tree[index << 1 | 1].minval);
}

void Build(int l, int r, int index){
    tree[index].l = l;
    tree[index].r = r;
    tree[index].minval = INF;
    if(l == r){
        tree[index].minval = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    Build(l, mid, index << 1);
    Build(mid + 1, r, index << 1 | 1);
    Pushup(index);
}

void Updata(int l,int r,int index,int val){
	if(tree[index].l == tree[index].r){
        tree[index].minval = val;
		return;
	}
	int mid = tree[index].l + tree[index].r >> 1;
	if(l <= mid) Updata(l, r, index << 1, val);
	if(r > mid) Updata(l, r, index << 1 | 1, val);
	Pushup(index);
}


int query(int l, int r, int index){
    if(l <= tree[index].l && tree[index].r <= r){
        return tree[index].minval;
    }
    int mid = (tree[index].l + tree[index].r) >> 1;
    int res = INF;
    if(l <= mid) res = min(res, query(l, r, index << 1));
    if(r > mid) res = min(res, query(l, r, index << 1 | 1));
    return res;
}


int main()
{
    scanf("%d",&T);
    while(T --){
        scanf("%d",&n);
        for(int i = 1; i <= n; ++ i){
            while(sol[i].size()) sol[i].pop();
        }
        for(int i = 1; i <= n; ++ i){
            scanf("%d",&a[i]);
            sol[a[i]].push(i);
        }
        Build(1, n, 1);
        int flag = 0, k;
        for(int i = 1; i <= n; ++ i){
            int x; scanf("%d",&x);
            if(flag) continue;
            if(sol[x].size()){
                k = sol[x].front(); sol[x].pop();
                int tt = query(1, k, 1);
                if(tt == x)  Updata(k, k, 1, INF);
                else flag = 1;
            }
            else flag = 1;
        }
        if(flag) printf("NO\n");
        else printf("YES\n");
    }
    return 0;
}


posted @ 2020-08-14 10:27  A_sc  阅读(74)  评论(0编辑  收藏  举报