美文网首页
Greedy Sequence

Greedy Sequence

作者: 雨落八千里 | 来源:发表于2019-09-26 22:42 被阅读0次

Greedy Sequence

题意:

  • 给你一个长度为n序列a,然后输出n个序列s的最大长度,每个序列s_i的第1个数都是i,后面的数必须满足si_j<=si_{j-1}并且后面的数都应该在序列a中寻找。而pos数组表示的是a数组中每个数的下标,在序列Si中相邻数在序列a中的下标不能超过k
    每个元素的下一个元素一定是与他距离不超过 k 的所有元素中,权值最大 的元素。
    样例2:
    S_1: 1
    S_2: 2
    S_3: 3 1
    S_4: 4 3 1
    S_5: 5 2
    S_6: 6 5 2
    S_7: 7 5 2

思路:

  • 因为n个序列s,每个序列s的第一个数字都是i,那么只要找出数字i在序列a的对应下标x,然后再找出i-1再序列a中的下标y,比较两者下标的差的绝对值是否小于等于k,那么假如小于k,那么序列S_i的长度等于序列S_{i-1}的长度加1,否则找出i-2再序列a中的下标重复操作找出序列S_i的长度
#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;
}
  • set预处理找出每个a_i下标在i-k~i+ka_i小的最大值存入pre数组。
  • 输出时,每个序列s_i的第1位是i,在序列a中找到对应的a[i]==i,从当前位置开始查找满足序列S_i的最长长度,于是pre数组就找出了a[i]在下标i-k~i+k中比a_i小的最大值。序列S中每个数的下一位都是比它小的最大值。所以ans[i]=ans[pre[i]]+1
#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;
}

相关文章

网友评论

      本文标题:Greedy Sequence

      本文链接:https://www.haomeiwen.com/subject/jodryctx.html