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;
}