思路
作者一开始把题读漏了,没看着 p , q p,\,q p,q 都是 1 ∼ n 1\sim n 1∼n 排列,还在想着要处理 p p p 值相等的情况,于是直接卡死了。(应该没有人像我这样吧)
我们用 a i a_i ai 表示可能支配 i i i 的位置个数,初始值就是有几个 j > i j>i j>i 满足 p j > p i p_j>p_i pj>pi。从 1 1 1 开始从小往大往 q q q 里面填值。 在填 1 1 1 的时候, q q q 里面还没有值,未来也不可能有比 1 1 1 小的值,如果在 q i q_i qi 处填 1 1 1,所有 j > i , p j > p i j>i,\,p_j>p_i j>i,pj>pi 的都一定支配 i i i,所以必须满足 d i = a i d_i=a_i di=ai。我们要做的就是找到一个位置 d i = a i d_i=a_i di=ai,然后把 1 1 1 扔进去。
那如果有很多位置都相等呢?我们先来看看把 1 1 1 放进去之后有什么影响。由于这个位置一定比未来填写的位置要更小,不能再支配别人,所以它必须从 j < i , p j < p i j<i,\,p_j<p_i j<i,pj<pi 的 j j j 的可能支配位置中移除,这些 j j j 的 a j a_j aj 需要减一。对于其他位置就没有影响了。进行完这个操作之后,就可以填入 2 2 2,此时 2 2 2 是所有有影响的 q q q 值中最小的( q i = 1 q_i=1 qi=1 的位置对其他位置的影响已经通过把 a j a_j aj 减一消除了),就和上面填 1 1 1 的做法一样。接下来也能用一样的方法填入 3 , 4 , 5 , ... 3,\,4,\,5,\dots 3,4,5,...。
现在我们再考虑多个位置满足条件的情况。此时必须选择最前面的位置,如果选了不是最前面的位置 i i i,会把一些 j < i j<i j<i 的 a j a_j aj 减一,然而在 i i i 之前的一些 a j a_j aj 是和 d j d_j dj 相等的,那么减完之后 a j < d j a_j<d_j aj<dj。在整个过程中 a a a 单调不增,这样 a j a_j aj 就再也不可能等于 d j d_j dj 了,也不可能再有数填入位置 j j j,就无解了。
什么时候无解呢?上面提到过,如果出现一个 a i < d i a_i<d_i ai<di,就完蛋了。还有,如果找不到一个 a i = d i a_i=d_i ai=di,就是 a a a 都太大了,也无解。
代码
cpp
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define ll long long
int t,n,p[5005],d[5005],a[5005],q[5005];
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++) a[i]=q[i]=0;
for(int i=1;i<=n;i++){
cin>>p[i];
for(int j=1;j<i;j++)
if(p[j]<p[i]) a[j]++;
}
for(int i=1;i<=n;i++) cin>>d[i];
bool succ=1;
for(int i=1;i<=n;i++){
int rec=0;
for(int j=1;j<=n;j++){
if(q[j]) continue;
if(a[j]==d[j]){
q[j]=i;
rec=j;
break;
}
if(a[j]<d[j]){
succ=0;
break;
}
}
if(rec==0) succ=0;
if(!succ) break;
for(int j=1;j<rec;j++)
if(p[j]<p[rec]) a[j]--;
}
if(succ){
for(int i=1;i<=n;i++) cout<<q[i]<<' ';
cout<<endl;
}
else cout<<"-1\n";
}
}