题意:
题意: 从1到n一行内输出si,si为数字i开头的满足题目要求的序列长度。
题目要求此序列满足:
1.相邻两元素在原数组中的距离不超过k。
2.Sij<=sij-1
3.序列中无重复元素。
解析:
解法很暴力很思维
我们用第二个测试样例来讲解
S1 1 1
S2 2 1
S3 3,1 2
S4 4,3,1 3
S5 5,2 2
S6 6,5,2 3
S7 7,5,2 3
我们再求S4的时候,小于4的最大数x=3,又因为之前S3已经求解过了,所以答案就是1+S3 所以要把之前的答案记忆化
那么该如何处理小于i的最大数,我们可以暴力枚举,只要一开始把每个数的下标存起来即可
for(int i=2;i<=n;i++)
for(int j=i-1;j>=1;j--)
{
if(abs(id[j]-id[i])<=k)
{
m[i]=j;
break;
}
}
对于所有的i小于它的最大数就已经处理完成了,剩下的就跑循环搜索吧。
我认为循环最多2次,最少1次
所以时间复杂度在O(2*n)
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int t,n,k;
int id[N],a[N],sum[N],m[N];
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d %d",&n,&k);
for(int i =1;i<=n;i++) scanf("%d",&a[i]),id[a[i]]=i;
memset(m,0,sizeof m);
m[1]=0;
for(int i=2;i<=n;i++)
for(int j=i-1;j>=1;j--)
{
if(abs(id[j]-id[i])<=k)
{
m[i]=j;
break;
}
}
for(int i=1;i<=n;i++)
{
sum[i]=0;
int p=i;
while(p)
{
int maxx=m[i];
if(sum[maxx]!=0)
{
sum[i]=sum[i]+sum[maxx]+1;
break;
}
sum[i]++;
p=maxx;
}
}
for(int i=1;i<=n;i++)
{
if(i==1) printf("%d",sum[i]);
else printf(" %d",sum[i]);
}
printf("\n");
}
}