用C++讲解以下题目:MX 在研究排列所具有的性质。这一天她拿出了 �n 张卡片排成一排想要在上面填数以写成一个 1∼�1∼n 的排列。Piggy 趁 MX 不注意偷偷在一些卡片上写了数。题目描述MX 很快发现了这一切。不过她并不生气而是考虑一个有趣的问题:如果我在上面填一些数让它依然构成一个排列且它的最长上升子序列长度为 �−1n−1MX 有多少种填数方法呢?Piggy 比较良心。他没有在不同的
首先,我们需要知道最长上升子序列的定义。一个序列中的最长上升子序列是指序列中一些元素按照原有的顺序排列,并且满足元素的值逐渐增大。例如,序列[1, 3, 2, 4, 5]中的最长上升子序列为[1, 2, 4, 5],长度为4。
根据题目要求,我们需要填入一些数使得原序列仍然是一个排列,并且最长上升子序列的长度为n-1。假设原序列为A,我们需要填入的数为B。那么A和B合并后的序列的最长上升子序列长度应该为n-1。
我们可以通过动态规划的方法来解决这个问题。定义一个数组dp,dp[i]表示以第i个数结尾的最长上升子序列的长度。初始时,dp[i]都为1,表示以第i个数结尾的最长上升子序列长度至少为1。
然后,我们遍历数组A中的每个数,计算dp[i]的值。对于每个dp[i],我们需要找到它之前的所有dp[j],其中j < i,且A[j] < A[i],然后更新dp[i]的值为dp[j]+1中的最大值。即:
dp[i] = max(dp[j]+1),其中j < i,且A[j] < A[i]
最后,我们遍历dp数组,找到最大的dp[i],即为最长上升子序列的长度。如果最长上升子序列的长度为n-1,说明填入的数B满足条件。否则,填入的数B不满足条件。
具体的算法实现如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n, q;
cin >> n >> q;
vector<int> A(n+1);
vector<int> dp(n+1, 1);
for (int i = 1; i <= 2*q; i += 2) {
int x, y;
cin >> x >> y;
A[x] = y;
}
for (int i = 2*q+1; i <= n; i++) {
A[i] = -1; // 未填入的数用-1表示
}
for (int i = 2; i <= n; i++) {
for (int j = 1; j < i; j++) {
if (A[j] < A[i]) {
dp[i] = max(dp[i], dp[j]+1);
}
}
}
int longest = *max_element(dp.begin(), dp.end());
if (longest == n-1) {
cout << "1" << endl;
} else {
cout << "0" << endl;
}
}
return 0;
}
该算法的时间复杂度为O(n^2),其中n为卡牌的个数
原文地址: https://www.cveoy.top/t/topic/h0vX 著作权归作者所有。请勿转载和采集!