题目
D. Subarray Sorting 线段树 队列
题意:数列a和数列b, 判断a数列能否数次任意区间上递增排序生成数列b
思路:输入数列a时建立线段树,并把每个数的位置记录到队列,输入数列bi时,枚举判断在a中bi之前,是否存在比biz更小的数,如果有,则无解,不能转换。
#include<bits/stdc++.h>
using namespace std;
int n;
int a[1200020],b[1200005];
int exppp[300005],expp[300005];
queue<int> q[300005];
void update(int o,int l,int r,int k,int v)
{
if(l==r)
{
a[o]=v;
return ;
}
int m=(l+r)/2;
if(k<=m) update(o*2,l,m,k,v);
else update(o*2+1,m+1,r,k,v);
a[o]=min(a[o*2],a[o*2+1]);
}
int getmin(int o,int l,int r,int ql,int qr)
{
if(ql<=l&&r<=qr)
{
return a[o];
}
int m=(l+r)/2;
int ll=1000000000;
if(ql<=m) ll=min(ll,getmin(o*2,l,m,ql,qr));
if(m+1<=qr) ll=min(ll,getmin(o*2+1,m+1,r,ql,qr));
return ll;
}
int main()
{
int k;
cin>>k;
while(k--)
{
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%d",&exppp[i]);
q[exppp[i]].push(i);
update(1,1,n,i,exppp[i]);
}
int flat=0;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
if(!q[x].empty())
{
int f=q[x].front();q[x].pop();
if(getmin(1,1,n,1,f)<x)
{
flat=1;
}
else
{
update(1,1,n,f,1e9);
}
}
else
{
flat=1;
}
}
for(int i=1;i<=n;i++)
{
while(!q[exppp[i]].empty())
{
q[exppp[i]].pop();
}
}
if(flat==1) printf("NO\n");
else printf("YES\n");
}
}