Edu Codeforces Round 142 (Rated for Div. 2)-D. Fixed Prefix Permutations-置换、字典树
题目:https://codeforces.com/problemset/problem/1792/D
非常套路地,\(q_{p_j}\)看成映射就是\((p*q)(j)\),双射自然可逆,所以改成\(q(j)=p^{-1}(j)\)。
题目里的每个置换长度都不超过10(其实大一点也没问题),查询相当于对每个\(p\)查询所有排列里,排列的逆和他最长公共前缀的长度是多少,直接放到字典树里查询就ok了(感觉这个D比C还简单x)
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
typedef long long ll;
using namespace std;
const int N=5e4+5;
const int M=15;
int n,m,cnt,pos[M];
int tr[N*10][M],p[N][M];
void insert(int *p,int len){
int k=0;
rep(i,1,len){
if(!tr[k][p[i]])tr[k][p[i]]=++cnt;
k=tr[k][p[i]];
}
}
int query(int *p,int len){
int k=0;
rep(i,1,len){
if(tr[k][p[i]])k=tr[k][p[i]];
else return i-1;
}
return len;
}
int main(){
fastio;
int T;cin>>T;
while(T--){
cin>>n>>m;
rep(i,1,n){
rep(j,1,m){
cin>>p[i][j];
pos[p[i][j]]=j;
}
insert(pos,m);
}
rep(i,1,n)cout<<query(p[i],m)<<' ';
cout<<endl;
rep(i,0,cnt)rep(j,1,m)tr[i][j]=0;
cnt=0;
}
return 0;
}