D. Fixed Prefix Permutations

D. Fixed Prefix Permutations

You are given n permutations a1,a2,,an, each of length m. Recall that a permutation of length m is a sequence of m distinct integers from 1 to m.

Let the beauty of a permutation p1,p2,,pm be the largest k such that p1=1,p2=2,,pk=k. If p11, then the beauty is 0.

The product of two permutations pq is a permutation r such that rj=qpj.

For each i from 1 to n, print the largest beauty of a permutation aiaj over all j from 1 to n (possibly, i=j).

Input

The first line contains a single integer t (1t104) — the number of testcases.

The first line of each testcase contains two integers n and m (1n5104; 1m10) — the number of permutations and the length of each permutation.

The i-th of the next n lines contains a permutation aim distinct integers from 1 to m.

The sum of n doesn't exceed 5104 over all testcases.

Output

For each testcase, print n integers. The i-th value should be equal to the largest beauty of a permutation aiaj over all j (1jn).

Example

input

复制代码
3
3 4
2 4 1 3
1 2 4 3
2 1 3 4
2 2
1 2
2 1
8 10
3 4 9 6 10 2 7 8 1 5
3 9 1 8 5 7 4 10 2 6
3 10 1 7 5 9 6 4 2 8
1 2 3 4 8 6 10 7 9 5
1 2 3 4 10 6 8 5 7 9
9 6 1 2 10 4 7 8 3 5
7 9 3 2 5 6 4 8 1 10
9 4 3 7 5 6 1 10 8 2
复制代码

output

1 4 4 
2 2 
10 8 1 6 8 10 1 7 

 

解题思路

  暴力做法是直接枚举全部排列,本质上给定一个排列p,从所有的排列中找到一个qi使得pqi的美丽值最大,假设最大值为k,那么pqi得到的排列就是{1,2,k,qpk+1 ,,qpm}。注意到就是求从1开始的上升前缀最长是多少。因此可以考虑用trie来存n个排列的信息,然后再枚举每一个排列来得到答案。

  对于一个排列p,如果答案至少是1,那么首先就要找到第p[1]个位置是数值1的所有排列,以此类推如果答案至少是2,那么就要从第p[1]个位置是数值1的所有排列中再找到第p[2]个位置为2的排列。因此我们可以在trie中存每个排列中每个数值在排列中的下标位置,查询的时候就依次遍历p[i],这样就可以找到一个匹配的最大前缀。

  AC代码如下,时间复杂度为O(n×m)

复制代码
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int n, m;
 5 vector<vector<int>> a, tr;
 6 int idx;
 7 int pos[20];
 8 
 9 void insert() {
10     int p = 0;
11     for (int i = 1; i <= m; i++) {
12         if (!tr[p][pos[i]]) tr[p][pos[i]] = ++idx;
13         p = tr[p][pos[i]];
14     }
15 }
16 
17 int query(int u) {
18     int p = 0, ret = 0;
19     for (int i = 1; i <= m; i++) {
20         if (!tr[p][a[u][i]]) break;
21         ret++;
22         p = tr[p][a[u][i]];
23     }
24     return ret;
25 }
26 
27 void solve() {
28     scanf("%d %d", &n, &m);
29     idx = 0;
30     tr = vector<vector<int>>(n * m + 1, vector<int>(m + 1));
31     a = vector<vector<int>>(n + 1, vector<int>(m + 1));
32     for (int i = 1; i <= n; i++) {
33         for (int j = 1; j <= m; j++) {
34             scanf("%d", &a[i][j]);
35             pos[a[i][j]] = j;
36         }
37         insert();
38     }
39     for (int i = 1; i <= n; i++) {
40         printf("%d ", query(i));
41     }
42     printf("\n");
43 }
44 
45 int main() {
46     int t;
47     scanf("%d", &t);
48     while (t--) {
49         solve();
50     }
51 }
复制代码

 

参考资料

  Educational Codeforces Round 142 D(思维+字典树):https://zhuanlan.zhihu.com/p/600835977

posted @   onlyblues  阅读(202)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示