• HDU 6852 Increasing and Decreasing 构造


    题意:

    给你一个n,x,y。你需要找出来一个长度为n的序列,使得这个序列满足最长上升子序列长度为x,最长下降子序列长度为y。且这个序列中每个数字只能出现一次

    且要保证最后输出的序列的字典序最小

    题解:

    因为要保证字典序最小,那么肯定是使用前n个数,即[1,n]

    我们可以首先让下降子序列用最大的值,且把它们放在序列最后,例如n=10,x=5,y=5

    那么我们就让下降子序列使用6,7,8,9,10.而且把这5个数反转一下变成10,9,8,7,6追加到序列尾部

    那么剩下的n-y个数去构建出来一个最长上升子序列为x-1的序列就行

    为什么是x-1?因为最后y个数比前的任意一个数都要大,所以最长上升子序列部分这里也要占用1个位置

    然后我们挑选出来x-1个数组成上升序列,挑选出来的数用wi表示(还是用的上面10,5,5的例子)

    1 w1 2 w2 3 w3 4 w4

    这个序列的1,2,3,4这些位置可以用长度为y-1的下降序列来插入其中

    因为题目要求输出字典序最小,那么我们就把w4尽可能使用y-1个数,然后w3尽可能使用y-1个数,依次类推

    假设w1部分使用了h个数,那么1 w1这1+h个位置使用前h+1个数来构造序列

    这样构造就是最小的

    题目要特判x*y>=n&&x+y<=n+1输出NO,我的x+y<=n+1是找出来的,但是x*y>=n这个我也不清楚。。。。

    代码:

    #include<stack>
    #include<queue>
    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    const int maxn=1e5+10;
    const int mod=1e9+7;
    typedef long long ll;
    ll n,x,y,ans[maxn];
    ll pre[maxn],len[maxn];
    int main()
    {
        ll t;
        scanf("%lld",&t);
        while(t--)
        {
            scanf("%lld%lld%lld",&n,&x,&y);
            if(1ll*x*y>=n&&x+y<=n+1)
            {
                printf("YES
    ");
                ll res=n-y;
                for(ll i=1; i<=x-1; i++)  //枚举这是第几个空隙
                {
                    len[i]=res-1ll*(x-1-i)*y;  //应该向第i个空隙内插入多少数
                    if(len[i]<=0)    //x-1-i表示这个空隙之前有多少个空隙
                    {                //至于为什么要乘于y,是因为下降序列y-1个数,上升序列的一部分占1个位置
                        len[i]=1;
                    }
                    res=res-len[i];
                    pre[i]=pre[i-1]+len[i];
                }
                for(ll i=1; i<=x-1; i++)
                {
                    for(ll j=pre[i-1]+1; j<=pre[i]; j++)
                    {
                        ans[i]=pre[i]-j+pre[i-1]+1;  //这个就相当于用【1,n】这n个数,来构造长度为n的序列
                        printf("%lld ",ans[i]);
                    }
                }
                for(ll i=n; i>=n-y+1; i--)
                {
                    printf("%lld%c",i,i==n-y+1?'
    ':' ');
                }
            }
            else
            {
                printf("NO
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    How to Use HyperV Snapshot Revert, Apply, and Delete Options
    读取含有命名空间xml文件内容
    C# 如何判断文件属性(like: readonly)
    Winform: how to cancel the winform close when click the "x" button
    Android 程序打包及签名 【图解】
    【转】近两日极为纠结——游戏服务器,选择何种技术方案?(Python + SWIGRakNet + Lua)
    apk打包和反编译三、有关 Conversion to Dalvik format failed with error 1
    (转)投票软件识别验证码思路及方法
    如何解决Android中输入法挡住输入框的问题
    A folder failed to be renamed or moved安装Android SDK的问题
  • 原文地址:https://www.cnblogs.com/kongbursi-2292702937/p/13492484.html
Copyright © 2020-2023  润新知