zoukankan      html  css  js  c++  java
  • [贪心]JZOJ P3619——medians

    Description

    让我们定义A 为1, 2, 3,。。。, 2 * N - 1 的一个全排列。

    定义数列B 为A 的前缀的中位数形成的数列:B[i] 为A[1],A[2],。。。,A[2 * i - 1] 的中位数。

    注:对于M 个数的中位数(M 是奇数),可以通过排序后取中间的数得到。

    给出N 和数列B。找到一个全排列A 使得前缀中位数形成的数列恰好为B。

    Input

    输入包含两行。

    第一行包含一个整数N。

    第二行描述B:N 个整数,用空格隔开。

    Output

    输出A:含2 * N - 1 个空格隔开的整数的一行。如果有多个全排列A 能够形成输入的数列B,

    那么你可以输出任意一个。测试数据中保证总是存在解。

    Sample Input

    5

    1 3 3 4 5

    Sample Output

    1 9 3 2 4 8 7 5 6

    Data Constraint

    • 1 <= A[i] <= 2 * N - 1,对于任意i 从1 到2 * N - 1

    • 1 <= B[i] <= 2 * N - 1,对于任意i 从1 到N

    • 1 <= N <= 100 000

    • 60% 的数据有N <= 1000

    题解

    贪心大法
    易得,b[1]就是全排列的第一个数
    这题要分类讨论
        一:f[b[i]]==fase(也就之前出现过该中位数或被选过)
                ①b[i]==b[i-1] 之前将维护的最大和最小的数输出
                ②b[i]<b[i-1] 输出维护的最大的两个数
                ③b[i]>b[i-1] 输出维护的最小的两个数
        二:f[b[i]]==true(之前没有输出过)先将这个数输出
                ①a[i]<a[i-1] 输出维护最小的数
                ②a[i]>a[i-1] 输出维护最大的数
    

    代码

    #include<cstdio>
    #include<memory.h>
    #include<iostream>
    using namespace std;
    int n,m,l,r,a[100010],p,s,b; 
    bool f[100010];
    int main()
    {
        //freopen("medians.in","r",stdin);
        //freopen("medians.out","w",stdout);
        scanf("%d",&n);
        m=n*2-1;
        l=1; r=m;
        memset(f,true,sizeof(f));
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            if (i==1) 
            {
                f[a[i]]=false;
                printf("%d ",a[i]);
                if (a[i]==l) l++;
            }
            else 
            if (f[a[i]]==false)
            {
                if (a[i]>a[i-1])
                {
                    while (f[r]==false) r--;
                    printf("%d ",r);
                    f[r]=false;
                    r--;
                    while (f[r]==false) r--;
                    printf("%d ",r);
                    f[r]=false;
                    r--;
                }
                else 
                if (a[i]<a[i-1])
                {
                    while (f[l]==false) l++;
                    printf("%d ",l);
                    f[l]=false;
                    l++;
                    while (f[l]==false) l++;
                    printf("%d ",l);
                    f[l]=false;
                    l++;
                }
                else
                {
                    while (f[l]==false) l++;
                    printf("%d ",l);
                    f[l]=false;
                    l++;
                    while (f[r]==false) r--;
                    printf("%d ",r);
                    f[r]=false;
                    r--;
                }
            }
            else 
            {
                p=i*2-1;
                f[a[i]]=false;
                printf("%d ",a[i]); 
                if (a[i]==r) r--; 
                if (a[i]<a[i-1])
                {
                    while (f[l]==false) l++;
                    printf("%d ",l);
                    f[l]=false;
                    l++;
                }
                else
                {
                    while (f[r]==false) r--;
                    printf("%d ",r);
                    f[r]=false;
                    r--;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    大厂面试爱问的「调度算法」,20 张图一举拿下
    键盘敲入 A 字母时,操作系统期间发生了什么
    “花呗还不起了,能不能把支付宝服务器炸掉?”
    Tomcat 报SocketException 断开的管道错误
    linux中grep命令的用法
    Linux的关机与重启
    globbing:文件名通配
    转载:Git 团队协作中常用术语
    Java多线程学习笔记
    RectTransform简析
  • 原文地址:https://www.cnblogs.com/Comfortable/p/8412241.html
Copyright © 2011-2022 走看看