题意: 给一个数组a,一个数组b,每次可以选择数组a的一个区间并从小到大排序,问是否可以将数组a变成数组b.
思路: 其实相当于每次可以选择相邻的两个数字,将其从小到大排序.因为任何区间进行排序后的结果,都可以由每次选两个进行多次而得到.
我们来看这个样例:
a: 15 9 7 10 8
b: 7 8 9 15 10
对于操作a数组, 很明显第一步我们要把7挪到第一个位置,能把7挪到第一个位置的条件是区间[1,3]的最小值等于7,于是我们用线段树(线段树维护a数组)查询[1,3]的最小值即可. 第二步,我们要把8放到第二个位置,同理,[1,5]的最小值应该等于8,但是现在查询出来最小值等于7,但其实7已经放到第一个位置了,8的移动不应该被7影响.其实我们在移动完7之后,把7所在的位置的值设置为inf就好了,这样已经排好的7对8的移动就不会再产生影响了.
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <time.h>
#include <map>
#include <set>
#define mem(a,x) memset(a,x,sizeof(a))
#define gi(x) scanf("%d",&x)
#define gi2(x,y) scanf("%d%d",&x,&y)
#define gi3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define gll(x) scanf("%lld",&x)
#define gll2(x,y) scanf("%lld%lld",&x,&y)
using namespace std;
const double eps=1e-8;
typedef long long ll;
const int MAXN=300005;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
vector<int>a[MAXN];
vector<int>b[MAXN];
int n;
struct Node{
int l,r;
int val;
}node[MAXN<<2];
int bb[MAXN];
int aa[MAXN];
int book[MAXN];
void pushup(int i){
node[i].val=min(node[i<<1].val,node[i<<1|1].val);
}
void build(int l,int r,int i){
node[i].l=l;
node[i].r=r;
if(l==r){
node[i].val=aa[l];
return;
}
int mid=(l+r)/2;
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
pushup(i);
}
int query(int l,int r,int i){
if(node[i].l>=l&&node[i].r<=r){
return node[i].val;
}
int mid=(node[i].r+node[i].l)/2;
int ans=inf;
if(l<=mid){
ans=query(l,r, i<<1);
}
if(r>=mid+1){
ans=min(ans,query(l, r, i<<1|1));
}
return ans;
}
void update(int i,int x){
if(node[i].l==node[i].r){
node[i].val=inf;
return;
}
int mid=(node[i].r+node[i].l)/2;
if(x<=mid)update(i<<1, x);
else update(i<<1|1, x);
pushup(i);
}
int main(){
int T;
gi(T);
while(T--){
int n;
gi(n);
for(int i=1;i<=n;i++){
a[i].clear();
b[i].clear();
}
for(int i=1;i<=n;i++){
gi(aa[i]);
a[aa[i]].push_back(i);
}
for(int i=1;i<=n;i++){
book[i]=0;
gi(bb[i]);
b[bb[i]].push_back(i);
}
int flag=0;
for(int i=1;i<=n;i++){
if(a[i].size()!=b[i].size()){
flag=1;break;
}
for(int j=0;j<a[i].size();j++){
book[b[i][j]]=a[i][j];//book[i]代表在b中下标为i的数字应该由在a中下标为book[i]的数字移动得到
}
}
if(flag){printf("NO\n");continue;}
build(1,n,1);
for(int i=1;i<=n;i++){
int t=book[i];
int minn=query(1, t, 1);
if(minn==bb[i]){
update(1, t);//设置成inf
}
else{
flag=1;
break;
}
}
if(flag){
printf("NO\n");
}
else printf("YES\n");
}
return 0;
}