[codeforces 1187D]Subarray Sorting

探讨给定两个等长数组a和b,通过选择a中的区间使其变为升序的方式,判断是否能在若干次操作后使a与b相等。采用线段树进行高效查询与更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

time limit per test:2 seconds
memory limit per test:256 megabytes

You are given an array a1a_1a1,a2a_2a2,…,ana_nan and an array b1b_1b1,b2b_2b2,…,bnb_nbn.
For one operation you can sort in non-decreasing order any subarray a[l…r]a[l…r]a[lr]
of the array aaa.

For example, if a=[4,2,2,1,3,1]a=[4,2,2,1,3,1]a=[4,2,2,1,3,1] and you choose subbarray a[2…5]a[2…5]a[25], then the array turns into [4,1,2,2,3,1][4,1,2,2,3,1][4,1,2,2,3,1].
You are asked to determine whether it is possible to obtain the array bbb
by applying this operation any number of times (possibly zero) to the array aaa.

Input

The first line contains one integer t(1≤t≤3⋅105)t(1≤t≤3⋅10^5)t(1t3105) — the number of queries.
The first line of each query contains one integer n(1≤n≤3⋅105)n(1≤n≤3⋅10^5)n(1n3105).
The second line of each query contains nnn integers a1,a2,…,an(1≤ai≤n)a_1,a_2,…,a_n (1≤a_i≤n)a1,a2,,an(1ain).
The third line of each query contains nnn integers b1,b2,…,bn(1≤bi≤n)b_1,b_2,…,b_n (1≤bi≤n)b1,b2,,bn(1bin).
It is guaranteed that ∑n≤3⋅105∑n≤3⋅10^5n3105 over all queries in a test.

Output

For each query print YESYESYES (in any letter case) if it is possible to obtain an array bbb and NONONO (in any letter case) otherwise.

Example
Input

4
7
1 7 1 4 4 5 6
1 1 4 4 5 7 6
5
1 1 3 3 5
1 1 3 3 5
2
1 1
1 2
3
1 2 3
3 2 1

Output

YES
YES
NO
NO

Note

In first test case the can sort subarray a1…a5a_1…a_5a1a5 , then aaa will turn into [1,1,4,4,7,5,6][1,1,4,4,7,5,6][1,1,4,4,7,5,6], and then sort subarray a5…a6a5…a6a5a6.

题意:
给定两个等长的数组a,ba,ba,b,定义操作为选取a中的一个区间让其变为升序,问是否存在若干次操作之后,a数组与b数组相同。
题解:
首先,我们先确定一个事情:我们将操作的区间长度设置为2。这样就可以像冒泡排序一样操作a序列了。
那么现在的问题就是,b序列是否是a序列冒泡排序中的一个状态。
首先我们知道,如果一个a[i]a[i]a[i]能被移动到数组的位置j(j&lt;i)j(j&lt;i)jj<i那么对于iiijjj之间的所有数字,他们的值一定小于a[i]a[i]a[i]
那么我们顺序遍历bbb数组,对于每一个b[i]b[i]b[i]我们找到在aaa数组中最靠左边的等于b[i]b[i]b[i]a[i]a[i]a[i]
而且这个b[i]b[i]b[i]还要不能比它前面的,还未被选中的数字要大。如果存在这样的a[i]a[i]a[i]那么我们就选中它,否则直接输出NO。这样做nnn次即可。这个操作我们可以用线段树来实现。

#include<bits/stdc++.h>
using namespace std;
struct seg{
    int l,r,w;
}tr[1200004];
int n,a[300004],b[300004];
void build(int k,int l,int r){
    tr[k].l=l;tr[k].r=r;
    if(l==r){
        tr[k].w=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    tr[k].w=min(tr[k<<1].w,tr[k<<1|1].w);
}
void modify(int k,int pos,int v){
    int l=tr[k].l,r=tr[k].r;
    if(l==r&&r==pos){
        tr[k].w=v;
        return ;
    }
    int mid=(l+r)>>1;
    if(pos<=mid)modify(k<<1,pos,v);
    else modify(k<<1|1,pos,v);
    tr[k].w=min(tr[k<<1].w,tr[k<<1|1].w);
}
int query(int k,int v){
    int l=tr[k].l,r=tr[k].r;
    if(l==r){
        if(tr[k].w==v)return r;
        else return -1;
    }
    int mid=(l+r)>>1;
    if(tr[k<<1].w<=v)return query(k<<1,v);
    else return query(k<<1|1,v);
}
int w33ha(){
    scanf("%d",&n);
    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=1;i<=n;i++){
        int now=query(1,b[i]);
        if(now==-1)return puts("NO"),0;
        modify(1,now,n+1);
    }
    puts("YES");
    return 0;
}
int main(){
    int T;scanf("%d",&T);
    while(T--)w33ha();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值