原题链接
https://ac.nowcoder.com/acm/contest/11253/K
题目大意
数组 b b b由排列 a a a按一下伪代码生成得到:
for i = 1 to n :
while ( Stk is not empty ) and ( Stk's top > a[i] ) :
pop Stk
push a[i]
b[i]=Stk's size
有一个长度为 n ( n ≤ 1 0 6 ) n(n\leq 10^6) n(n≤106)的数组 b b b,只知道其中的 k k k项( p i , x i p_i,x_i pi,xi),求排列 a a a。若有则输出任意一种即可,若没有则输出 − 1 -1 −1。
题解
可以根据题目所给的伪代码进行反推,举个例子:
设
b
[
1...5
]
=
{
1
,
2
,
1
,
2
,
3
}
设b[1...5]=\{1,2,1,2,3\}
设b[1...5]={1,2,1,2,3},此时数字
1
1
1 只能放在
a
3
a_3
a3,数字
2
2
2 可以放在
a
1
a_1
a1或
a
4
a_4
a4,数字
3
3
3 可以放在①
a
1
a_1
a1或
a
5
a_5
a5
(
a
4
=
2
)
(a_4=2)
(a4=2),②
a
2
a_2
a2
(
a
1
=
2
)
(a_1=2)
(a1=2),依次类推。
当栈中的元素数量 < < < b i b_i bi时,对栈中的数字进行补充。
由于存在多种情况,我们可以将当前步骤数字(栈顶元素)放在:
①上一步放置的位置之后
②上一步放置位置之前
b
i
b_i
bi为
1
1
1处(上一步放置位置之后已有数字)
同时,
b
b
b数组也存在多种情况,这是我觉得比较简单的情况:
当
b
i
b_i
bi的值未确定时,
b
i
=
b
i
−
1
+
1
b_i=b_{i-1}+1
bi=bi−1+1。
若 b b b数组不合理,则输出 − 1 -1 −1,因为 b i b_i bi的最大值为 i i i,所以当 p i < x i p_i<x_i pi<xi时,不存在合理方案。
参考代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int n,k,x,y,p=0;
int b[N],a[N];
int main()
{
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
{
scanf("%d%d",&x,&y);
b[x]=y;
if(x<y)
{
printf("-1");
return 0;
}
}
for(int i=1;i<=n;i++)
if(b[i]==0)b[i]=b[i-1]+1;
stack<int> st;
for(int i=n;i>=1;i--)
{
if(st.size()<b[i])
for(int j=st.size()+1;j<=b[i];j++)
{
p++;//p为目前使用过的元素最大值
st.push(p);//补充栈中的元素
}
a[i]=st.top();
st.pop();
}
for(int i=1;i<=n;i++)printf("%d ",a[i]);
}