美文网首页
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