题意:
现在有两个数组,并且你每次可以做一个操作:选择一个区间,并且排序。
问你对上面这个数组做一些操作之后是否能得到下面这个数组。
题解:
那么如果每次选的区间大小为2,那么就像是一个冒泡排序了,将一个大的值依次向后传并且保持其他的值顺序不变。
那么我们只需要从后往前枚举一遍b数组,然后查看a数组对应的bi的值的最后一个位置到n的最大值是否有一个数大于他。如果有就不行,因为他没有办法交换到后面去。如果行那就将这个值去掉,因为它已经排好了。我用线段树维护最大值。
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int a[N],b[N],mx[N*4];
queue<int>Q[N];
void update(int l,int r,int root,int p,int v){
if(l==r){
mx[root]=v;
return ;
}
int mid=l+r>>1;
if(mid>=p)
update(l,mid,root<<1,p,v);
else
update(mid+1,r,root<<1|1,p,v);
mx[root]=max(mx[root<<1],mx[root<<1|1]);
}
int query(int l,int r,int root,int ql,int qr){
if(l>=ql&&r<=qr)
return mx[root];
int mid=l+r>>1,ans=0;
if(mid>=ql)
ans=query(l,mid,root<<1,ql,qr);
if(mid<qr)
ans=max(ans,query(mid+1,r,root<<1|1,ql,qr));
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),update(1,n,1,i,a[i]);
for(int i=n;i;i--)
Q[a[i]].push(i);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
int f=0;
for(int i=n;i;i--){
if(Q[b[i]].empty()){
f=1;
break;
}
int p=Q[b[i]].front();
Q[b[i]].pop();
if(query(1,n,1,p,n)>b[i]){
f=1;
break;
}
update(1,n,1,p,0);
}
for(int i=1;i<=n;i++)while(!Q[i].empty())Q[i].pop();
if(f)printf("NO\n");
else printf("YES\n");
}
return 0;
}