解题过程的小记录,如有错误欢迎指出。
难度:三星(最长递增序列的变形题,最后两个测试点数据量较大,用set会超时,用邻接矩阵可以)
题目分析
给出一串数列,要求找出最长的按照指定的增减顺序的子序列
注意点
- 最后两个测试点的数据量较大,要选择采用省时的方法
我的解题过程
思路
- 因为本题的总颜色数不超过200个,所以用邻接矩阵pre[i][j]保存颜色i前面可以连着的颜色j,数组类型为bool,当前面可以存在某数时为true
- 然后就是套的最长递增数列的模板,用dp[i]记录以i结尾的最长序列,ans保存最长序列长度
bug
- 用set设置每个颜色的前驱数组,然后在后面查找最长序列的时候用find进行判断,有两个测试点会超时
代码
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN = 205;
int dp[10005], order[MAXN];
bool pre[MAXN][MAXN];
int main()
{
int n;
scanf("%d", &n);
int m;
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
scanf("%d", &order[i]);
}
fill(pre[0], pre[0] + MAXN*MAXN, false);
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= i; j++) {
pre[order[i]][order[j]] = true;
}
}
int L[10005];
int length;
scanf("%d", &length);
for (int i = 1; i <= length; i++) {
scanf("%d", &L[i]);
}
int ans = 0;
for (int i = 1; i <= length; i++) {
dp[i] = 1;
for (int j = 1; j < i; j++) {
if (pre[L[i]][L[j]]==true && dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1;
}
}
ans = max(ans, dp[i]);
}
printf("%d", ans);
return 0;
}
dalao的代码
全部代码因版权原因不放出来,大家可以自行去柳神博客购买或者参考晴神的上机笔记~
借鉴点
- 建议参考一下算法笔记上对应章节的模板
- 可以采用映射将不单调递增的序列映射到hash表上就边成了单调递增序列
- 因为L的长度较大,如果要做时间上的优化可以把L数组中不是Eva喜欢的颜色给直接去掉,这样L的长度会缩短,在进行为dp赋值的时候节省时间
- 本题可以去看一下上机宝典的对应章节,做法值得参考(不愧是30分的题orz)