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