题意:给两个数字序列a,b,在给出m次区间,每次区间操作可以对L[i]~R[i]间的数字进行任意排列,问序列a能否在m次操作后变为序列b.
思路:贪心思想,每次操作都使a[i]尽可能的靠近它的期望位置,所以对每个操作区间按照它的期望位置排序,结果和b序列一样那就YES。O(n^2)可以处理出每个a[i]的期望位置。
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #define LL long long #define eps 1e-8 #define maxn 150 #define mod 110119 #define inf 0x3f3f3f3f #define IN freopen("in.txt","r",stdin); using namespace std; struct node{ int num; int to; }a[1005]; int b[1005]; int L[1005],R[1005]; bool vis[1005]; bool cmp(struct node x,struct node y){ return x.to<y.to; } int main(){ // IN; int t; int n,m; cin>>t; while(t--){ memset(vis,false,sizeof(vis)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i].num); } for(int i=1;i<=n;i++){ scanf("%d",&b[i]); } for(int i=1;i<=m;i++){ scanf("%d%d",&L[i],&R[i]); } int sign1=0,sign2=0; for(int i=1;i<=n;i++){ sign1=0; for(int j=1;j<=n;j++){ if(a[i].num==b[j] && !vis[j]){ a[i].to=j; vis[j]=true; sign1=1; break; } } if(sign1==0) sign2=1; } if(sign2==1){ printf("No\n"); continue; } for(int i=1;i<=m;i++){ sort(a+L[i],a+R[i]+1,cmp); } sign2=0; for(int i=1;i<=n;i++){ if(a[i].num!=b[i]){ sign2=1; break; } } if(sign2==1){ printf("No\n"); }else{ printf("Yes\n"); } } return 0; }