链接:https://community.topcoder.com/stat?c=problem_statement&pm=14607&rd=16933
题意:给一个排列p[n],定义f(k)表示它长度为k的所有子序列提取出来,对于每一个按大小顺序标号之后形成的本质不同的排列个数是否为C(n, k),现在你要补全一个排列,使∑f(k)最大,然后字典序最小
题解:考虑f(n - 1) = 1的时候,我们注意到只要相邻两个之差不为1就行了
然后f(n - k) = 1的时候,归纳一下就可以发现只要min(|i - j| + |p[i] - p[j]|) >= k就可以了
证明挺简单的
然后就直接搜就好了
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair < int, int > pii;
class PermutationSubsequence
{
public:
inline bool Dfs(vector < int > &cur, vector < int > &p, int x, int n, int v, int S)
{
if (x == n)
return true;
if (~p[x])
{
for (int i = 0; i < x; i ++)
if (x - i + abs(p[x] - cur[i]) < v)
return false;
cur[x] = p[x];
if (Dfs(cur, p, x + 1, n, v, S))
return true;
}
for (int i = 0; i < n; i ++)
if (S >> i & 1)
{
bool f = 1;
for (int j = 0; j < x; j ++)
if (x - j + abs(i - cur[j]) < v)
f = 0;
if (f)
{
cur[x] = i;
if (Dfs(cur, p, x + 1, n, v, S ^ 1 << i))
return true;
}
}
return false;
}
vector < int > findBest(vector < int > arr)
{
int n = arr.size(), S = (1 << n) - 1;
vector < int > ans(n);
for (int i = 0; i < n; i ++)
if (~arr[i])
S ^= 1 << arr[i];
for (int i = n; i; i --)
if (Dfs(ans, arr, 0, n, i, S))
return ans;
}
};