JZOJsenior3619.【BOI2011】medians

problem

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


analysis

  • 其实这个用最最最基础的贪心就可以过了,你看这数据水的——

  • 如果 b[i]>b[i1] ,中位数变大就插进当前的数和最大的数

  • 如果 b[i]<b[i1] ,中位数变小就插进当前的数和最小的数

  • 中位数不变就插进最大和最小的即可

  • 用两个指针搞一搞,注意判断数出现过了没有就好了


code

#include<stdio.h>
#include<string.h>
#define MAXN 100001

using namespace std;

int a[MAXN*2],b[MAXN],f[MAXN*2];
bool bz[2*MAXN];
int n,mn,mx,tot;

int read()
{
    int x=0,f=1;
    char ch=getchar();
    while (ch<'0' || '9'<ch)
    {
        if (ch=='-')f=-1;
        ch=getchar();   
    }
    while ('0'<=ch && ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

int main()
{
    freopen("medians.in","r",stdin); 
    freopen("medians.out","w",stdout);
    n=read();
    for (int i=1;i<=n;i++)b[i]=read();
    bz[0]=bz[2*n]=bz[b[1]]=1;
    mn=1,mx=2*n-1;
    f[1]=b[1],tot=1;
    for (int i=2;i<=n;i++)
    {
        if (b[i]==b[i-1])
        {
            while (bz[mx])mx--;
            bz[mx]=1;
            f[++tot]=mx;
            while (bz[mn])mn++;
            bz[mn]=1;
            f[++tot]=mn;
        }
        else if (b[i]>b[i-1])
        {
            while (bz[mx])mx--;
            bz[mx]=1;
            f[++tot]=mx;
            if (!bz[b[i]])bz[b[i]]=1,f[++tot]=b[i];
            else
            {
                while (bz[mx])mx--;
                bz[mx]=1;
                f[++tot]=mx;
            }
        }
        else if (b[i]<b[i-1])
        {
            while (bz[mn])mn++;
            bz[mn]=1;
            f[++tot]=mn;
            if (!bz[b[i]])bz[b[i]]=1,f[++tot]=b[i];
            else
            {   
                while (bz[mn])mn++;
                bz[mn]=1;
                f[++tot]=mn;
            }
        }
    }
    for (int i=1;i<=2*n-1;i++)
    {
        printf("%d ",f[i]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值