D. Fixed Prefix Permutations
D. Fixed Prefix Permutations
You are given permutations , each of length . Recall that a permutation of length is a sequence of distinct integers from to .
Let the beauty of a permutation be the largest such that . If , then the beauty is .
The product of two permutations is a permutation such that .
For each from to , print the largest beauty of a permutation over all from to (possibly, ).
Input
The first line contains a single integer () — the number of testcases.
The first line of each testcase contains two integers and (; ) — the number of permutations and the length of each permutation.
The -th of the next lines contains a permutation — distinct integers from to .
The sum of doesn't exceed over all testcases.
Output
For each testcase, print integers. The -th value should be equal to the largest beauty of a permutation over all ().
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
解题思路
暴力做法是直接枚举全部排列,本质上给定一个排列,从所有的排列中找到一个使得的美丽值最大,假设最大值为,那么得到的排列就是。注意到就是求从开始的上升前缀最长是多少。因此可以考虑用trie来存个排列的信息,然后再枚举每一个排列来得到答案。
对于一个排列,如果答案至少是,那么首先就要找到第个位置是数值的所有排列,以此类推如果答案至少是,那么就要从第个位置是数值的所有排列中再找到第个位置为的排列。因此我们可以在trie中存每个排列中每个数值在排列中的下标位置,查询的时候就依次遍历,这样就可以找到一个匹配的最大前缀。
AC代码如下,时间复杂度为:
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
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17068988.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效