Greedy Sequence
题意:
- 给你一个长度为
序列
,然后输出
个序列
的最大长度,每个序列
的第
个数都是
,后面的数必须满足
并且后面的数都应该在序列
中寻找。而
数组表示的是
数组中每个数的下标,在序列
中相邻数在序列
中的下标不能超过
每个元素的下一个元素一定是与他距离不超过 k 的所有元素中,权值最大 的元素。
样例2:
1
2
3 1
4 3 1
5 2
6 5 2
7 5 2
思路:
- 因为
个序列
,每个序列
的第一个数字都是
,那么只要找出数字
在序列
的对应下标
,然后再找出
再序列
中的下标
,比较两者下标的差的绝对值是否小于等于
,那么假如小于
,那么序列
的长度等于序列
的长度加1,否则找出
再序列
中的下标重复操作找出序列
的长度
#include <bits/stdc++.h>
using namespace std;
const int M=1e5+10;
int a[M];
int n,x,k;
int ans[M];
int main( )
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
a[x]=i;//每个数出现的下标
}
for(int i=1;i<=n;i++)
{
ans[i]=1;
for(int j=i-1;j>=1;j--)//寻找下一个从大到小寻找
{
if(abs(a[j]-a[i])<=k)
{
ans[i]=ans[j]+1;
break;
}
}
printf("%d%c",ans[i],i==n?' ':'\n');
}
}
return 0;
}
- 用
预处理找出每个
下标在
~
比
小的最大值存入
数组。
- 输出时,每个序列
的第
位是
,在序列
中找到对应的
,从当前位置开始查找满足序列
的最长长度,于是
数组就找出了
在下标
~
中比
小的最大值。序列
中每个数的下一位都是比它小的最大值。所以
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+10;
int a[M],pre[M];
int ans[M];
int main( )
{
int t,n,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
set<int>s;
int l=1,r=min(k+1,n);//保证开始set中有k+1个数,set中最大的数的下标比最小数的下标差值绝对值为k
for(int i=l;i<=r;i++)
{
s.insert(a[i]);//从小到大排序
}
for(int i=1;i<=n;i++)
{
while(r-i<k&&r+1<=n)//保证i的右边最少有k个数
{
s.insert(a[++r]);
}
while(i-l>k)//保证i的左边最多k个数
{
s.erase(a[l++]);
}
set<int>::iterator it=s.lower_bound(a[i]);//找出第一个比a[i]大于或等于数的定位器
if(it==s.begin( ))//范围内没有比自己小的数
{
pre[a[i]]=0;
}
else
{
pre[a[i]]=*(--it);//大于等于a[i],a[i]已经在set中所以返回的是a[i]的定位器,找出最大的比a[i]的数就是a[i]的前一位,所以是*(--it);
}
}
ans[0]=0;
for(int i=1;i<=n;i++)
{
ans[i]=ans[pre[i]]+1;
printf("%d%c",ans[i],i!=n?' ':'\n');
}
}
return 0;
}
网友评论