[日常训练]变戏法
Description
一开始有$n$个只有颜色不同的小球。定义使用一次膜法的效果是重新排列第$l_i$个到第$r_i$个小球。给定了$n$个小球的初始状态和最终状态,以及$m$次膜法的范围$l_i,r_i$。判断是否可以从初始状态转移到最终状态。
Input
第一行有一个整数$t$表示数据组数。
每组数据中,
第一行两个整数$n,m$,表示总共有$n$个小球,$m$次操作。
第二行$n$个整数$a_i$,表示初始状态。
第三行$n$个整数$b_i$,表示最终状态。
接下来$m$行,每行两个整数$l_i,r_i$。
Output
输出共$t$行。对于每组数据,如果合法,输出"$TAK$",否则输出"$NIE$"。
Sample Input
3
10 3
1 2 3 4 5 6 7 8 9 10
2 1 3 6 4 5 9 8 7 10
4 8
1 3
5 9
10 3
1 2 3 4 5 6 7 8 9 10
2 1 3 6 10 4 5 9 8 7
4 8
1 3
5 9
10 3
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 9
4 8
1 3
5 9
Sample Output
TAK
NIE
NIE
HINT
$1\;\leq\;t\;\leq\;10,1\;\leq\;n,m,a_i,b_i\;\leq\;1000$.
Solution
对于颜色相同的小球,如果可行,一定存在一种不改变它们相对顺序的方法。所以我们可以将所有小球一一对应。然后将最终状态的小球从$1$到$n$标号,然后每次操作相当于区间排序。最后判断是否相等即可。
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 1005
using namespace std;
int a[N],c[N][N],t[N],n,m,ti;
bool flag;
inline int read(){
int ret=0;char c=getchar();
while(!isdigit(c))
c=getchar();
while(isdigit(c)){
ret=(ret<<1)+(ret<<3)+c-'0';
c=getchar();
}
return ret;
}
inline void Aireen(){
ti=read();
while(ti--){
n=read();m=read();
memset(t,0,sizeof(t));
for(int i=1;i<=n;++i)
a[i]=read();
for(int i=1,k;i<=n;++i){
k=read();c[k][++t[k]]=i;
}
for(int i=n,k;i;--i){
k=a[i];a[i]=c[k][t[k]--];
}
for(int i=1,l,r;i<=m;++i){
l=read();r=read();
sort(a+l,a+1+r);
}
flag=true;
for(int i=1;i<=n;++i)
if(a[i]!=a[i-1]+1){
flag=false;break;
}
if(flag) puts("TAK");
else puts("NIE");
}
}
int main(){
freopen("mogic.in","r",stdin);
freopen("mogic.out","w",stdout);
Aireen();
fclose(stdin);
fclose(stdout);
return 0;
}