Educational Codeforces Round 142 (Rated for Div. 2)

D. Fixed Prefix Permutations

题目大意
给定两个排列\(p,q\)\(r=p\cdot q\)表示\(r_j=q_{p_j}\)
一个排列\(p\)的美丽值为满足\(p_1=1,\ p_2=2,\ p_3=3,\ \cdots,\ p_k=k\)最大的\(k\),若\(p_1\neq 1\),则\(k=0\)
现给定\(n\)个长度一样的排列\(a[n]\),输出\(n\)个答案,第\(i\)个答案表示\(a_i\cdot a_j\ (1\le j \le n)\)的最大美丽值。

解题思路
\(k \neq 0\)的情况下我们有\(p\cdot q=(1,\ 2,\ \cdots,\ k,\ r_{k+1},\ \cdots,\ ,r_m)\),两边同时乘以\(q^{-1}(p^{-1}满足p\cdot q^{-1}=(1,\ 2,\ \cdots,\ n))\)得到\(p=(1,\ 2,\ \cdots,\ k,\ r_{k+1},\ \cdots,\ ,r_m)\cdot q^{-1}\),我们会发现\(p\)的前\(k\)个数与\(q^{-1}\)\(k\)个数相同。那么要找大最大的\(k\),就是对\(p\)而言找到具有最长相同前缀的\(q^{-1}\)

参考代码

#include <bits/stdc++.h>
using namespace std;
int get(vector<int> &a, vector<int> &b)
{
    int ans = 0;
    while (ans < a.size() && a[ans] == b[ans])
    {
        ++ans;
    }
    return ans;
}
void work()
{
    int n, m;
    cin >> n >> m;
    vector<vector<int>> a(n, vector<int>(m));
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            cin >> a[i][j];
            --a[i][j];
        }
    }
    vector<vector<int>> b(n, vector<int>(m));
    for (int i = 0; i < n; ++i)
    {
        for (int j = 0; j < m; ++j)
        {
            b[i][a[i][j]] = j;
        }
    }
    sort(b.begin(), b.end());
    for (int i = 0; i < n; ++i)
    {
        int ans = 0;
        int t = lower_bound(b.begin(), b.end(), a[i]) - b.begin();
        if (t > 0)
            ans = max(ans, get(b[t - 1], a[i]));
        if (t < n)
            ans = max(ans, get(b[t], a[i]));
            cout << ans << " ";
    }
    cout << endl;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin >> T;
    while (T--)
    {
        work();
    }
    return 0;
}
posted @ 2023-02-17 23:22  何太狼  阅读(21)  评论(0编辑  收藏  举报