希哥哥推荐的好题。
当k小于100,直接构造出来,然后直接求数组;当k大于100时,构造出 n 个原串,求其最长上升子序列,然后加上(k-n)*原串中出现次数最多的数的出现次数,即为答案。
再推荐一篇博客:https://blog.youkuaiyun.com/yjt9299/article/details/82966703
#include<bits/stdc++.h>
#define mem(a,b) memset((a),b,sizeof(a))
typedef long long ll;
const int N=100010;
using namespace std;
int a[10010],b[110],dp[10010];
int main()
{
mem(a,0);
mem(b,0);
mem(dp,0);
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
b[i]=0;
for(int j=1;j<=n;j++)
if(a[i]==a[j])
b[i]++;
}
int maxx=0;
for(int i=1;i<=n;i++)
maxx=max(maxx,b[i]);
int cnt;
if(k<=100)
{
cnt=n+1;
for(int i=2;i<=k;i++)
{
for(int j=1;j<=n;j++)
a[cnt++]=a[j];
//开始写错了,写成这样:a[cnt++]=a[(cnt-1)%n];
}
int ans=0;
for(int i=1;i<=n*k;i++)
{
dp[i]=1;
for(int j=1;j<i;j++)
{
if(a[i]>=a[j])
dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}
printf("%d",ans);
return 0;
}
cnt=n+1;
for(int i=2;i<=n;i++)
for(int j=1;j<=n;j++)
a[cnt++]=a[j];
ll ans=0;
for(int i=1;i<=n*n;i++)
{
dp[i]=1;
for(int j=1;j<i;j++)
{
if(a[i]>=a[j])
dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,(ll)dp[i]);
}
ans+=(k-n)*maxx;
printf("%I64d",ans);
return 0;
}
本文探讨了针对特定条件下的最长上升子序列问题的高效解决策略。当k小于100时,通过直接构造和计算得到结果;当k大于100时,采用先求原串的最长上升子序列,再结合重复次数最多的元素出现次数来优化计算。文章还分享了一篇详细解析此算法的博客链接。
807

被折叠的 条评论
为什么被折叠?



