zoukankan      html  css  js  c++  java
  • UPC-5618 K-th K(构造)

    题目描述
    You are given an integer sequence x of length N. Determine if there exists an integer sequence a that satisfies all of the following conditions, and if it exists, construct an instance of a.

    a is N2 in length, containing N copies of each of the integers 1, 2, …, N.
    For each 1≤i≤N, the i-th occurrence of the integer i from the left in a is the xi-th element of a from the left.
    Constraints
    1≤N≤500
    1≤xi≤N2
    All xi are distinct.
    输入
    The input is given from Standard Input in the following format:

    N
    x1 x2 … xN
    输出
    If there does not exist an integer sequence a that satisfies all the conditions, print ‘No’. If there does exist such an sequence a, print ‘Yes’.
    样例输入
    3
    1 5 9
    样例输出
    Yes

    题意:原题位于AtCoder,给出一个长度为n的序列a,要我们构造长度为n^2的序列b,在这个构造序列中要求满足,对于序列a中的元素,我们将在序列b中的第a【i】个位置恰好第i次出现数字i,即,a【i】表示了下标i在a【i】的第i次出现位置,所有1~n个数字都必须出现n次。在满足了第a【i】位出现第i次后,后续数位上的出现不做要求。 若能构造出这样的序列b输出Yes,否则输出No.

    根据题意模拟构造即可,首先根据每个下标I的第i次出现位置从小到大排序,我们将优先排列出现在较前位置的数字。使得位置靠前的数字能在前a【i】个位置中有足够的空间放置i-1个数量。

    对于某一个数,当我们发现排列的指针在构造i-1个数量的i时,位置超过了a【i】,说明构造失败,直接输出No

    在正向构造完之后,我们满足了每个数字应该在第a【i】位前放置i个i的条件,接下来就要满足整个序列中所有数的出现次数都是n的条件,接着刚才的指针向后填数,此时我们需要填的i的个数是n-pos个,此时注意,如果之前的val太大,那么序列的后半部分可能不够填n-pos个i,那么就要填在val之前,这样就会影响val的出现次数不是i,所以也是无解的情况,因此如果填数的指针小于val那么说明一定会影响到val的排位。

    代码如下

    #include<bits/stdc++.h>
    using namespace std;
    struct num
    {
        int val,pos;
    } a[508],b[508];
    bool cmp(num a,num b)
    {
        return a.val<b.val;
    }
    int ans[508*508];
    int main()
    {
        int n;
        while(scanf("%d",&n)!=EOF)
        {
            bool flag=true;
            memset(ans,0,sizeof(ans));
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&a[i].val);
                b[i].val=a[i].val;
                b[i].pos=a[i].pos=i;
            }
            sort(b+1,b+n+1,cmp);
            int it=1;
            for(int i=1; i<=n; i++)
            {
                ans[a[b[i].pos].val]=b[i].pos;
                for(int j=1; j<b[i].pos; j++) ///在第val为之前要填充pos个pos
                {
                    while(ans[it])it++;///只能在没有被填数的位置填
                    ans[it]=b[i].pos;
                }
                if(it>a[b[i].pos].val)///若填充超量说明根本不够构造
                {
                    printf("No
    ");
                    flag=false;
                    break;
                }
            }
            if(!flag) continue;
            for(int i=1; i<=n; i++) ///对于所有数,先正向填充,保证在val前能填充够pos个
            {
                for(int j=1; j<=n-b[i].pos; j++) ///再继续填充,前pos个能保证的情况下,在剩余空位能填充够n个
                {
                    while(ans[it])it++;
                    if(it<a[b[i].pos].val)
                    {
                        printf("No
    ");
                        flag=false;
                        break;
                    }
                    ans[it]=b[i].pos;
                }
                if(!flag) break;
            }
            if(flag)printf("Yes
    ");
    //        for(int i=1; i<=n*n; i++)printf("%d ",ans[i]);
        }
    }
    
  • 相关阅读:
    第四讲动手动脑集课后作业
    第三讲课后作业
    课后作业01
    《大道至简》第一章伪代码读后感
    第八周学习进度条
    第七周学习进度条
    求一维联通数组的最大子数组之和
    求二维数组的最大联通子数组之和
    第六周学习进度条
    求一个数组的最大子数组之和
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135781.html
Copyright © 2011-2022 走看看