首页 > 代码库 > [日常训练]变戏法

[日常训练]变戏法

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;
}

[日常训练]变戏法