一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情。
题目描述
这是4月6日代码源div2的每日一题。
知识点:dp
优美!最长上升子序列 - 题目 - Daimayuan Online Judge
多组数据。
每组将给定一个数组。派派希望从中选择一个递增的子序列,越长越好。
但派派认为,这样选出来的子序列依然不够「优美」,形式化的讲,派派希望选择的下标(从 1 开始)需要满足
i1∣i2∣i3∣⋯∣ik
其中 a|b 表示整除, 即 a 是 b 的约数。
请你帮助派派完成任务吧!
注:子序列的含义不再赘述。
输入格式
第一行一个整数 T,表示接下来有 T 组数据。
每组数据包含两行,第一行包含一个整数 N。
随后一行,包含 N 个整数,表示原数组 {A}。
输出格式
对于每组数据,输出一行,包含一个数,表示能选出的「优美」的最长上升子序列长度。
数据规模
- 1≤T≤100
- 1≤N≤10^6,但保证 ∑i=1TNi≤10^6
- 1≤Ai≤10^9
样例输入
4
4
1 4 6 7
2
2 2
10
1 2 3 4 5 6 7 8 9 10
10
10 9 8 6 5 2 3 1 2 1
样例输出
3
1
4
1
解释:
对于第一组数据,能选择的「优美」最长上升子序列为 {A1,A2,A4}={1,4,7}。
对于第三组数组,选择 {A1,A2,A4,A8}={1,2,4,8}。
对于第四组数据,可选择的「优美」最长上升子序列长度为 1。
问题解析
一开始有点懵,不理解是什么意思,后来发现跟一般的求最长上升子序列差不多。
这里和一般的求最长上升子序列就多了一个条件:选择的最长上升子序列,他们在数组v里的位置(从1开始,不是0)要呈倍数关系。那我从位置1开始,只看我枚举位置的倍数能不能凑成上升子序列就行。比如我枚举的位置是2,那我就看4 6 8……这些位置能不能和第二个位置凑成上升序列。我们可以准备一个dp数组,dp[i]的意思是,以v[i]为结尾的最长上升子序列的长度。我们就看,如果倍数位置j的数大于我们枚举的位置i的数,就看是当前dp[j]存的位置和dp[i]+1那个大。我们选最大的。最后输出dp数组里存储的最大值。
AC代码
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n';
typedef long long ll;
typedef pair<int, int> PII;
const int N = 4e5 + 50;
inline int read() {
int x = 0; char ch = getchar();
while (ch < '0' || ch > '9') ch = getchar();
while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
void write(int x) {
if (x > 9) write(x / 10);
putchar(x % 10 | '0');
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
t=read();
while (t--)
{
int n, mx = 1;
n=read();
vector<int>v(n+1), dp(n+1,1);
for (int i = 1; i <= n; i++)v[i]=read();
for (int i = 1; i <= n; i++)
{
for (int j = i * 2; j <= n; j += i)
{
if (v[j] > v[i])dp[j] = max(dp[j], dp[i] + 1);
mx = max(mx, dp[j]);
}
}
write(mx);
putchar('\n');
}
return 0;
}