传送门
先看AAA序列,如果要让AAA序列构成一棵树只需要将AAA序列中的所有节点向在它前面的节点连边即可,不过这不能保证这棵树的dfsdfsdfs序一定是AAA序列,因此这里要用到一个小技巧,我们每次都向最后加的一条边的两个端点中的其中一个端点连边即可,这样一定能保证是dfsdfsdfs序一定是AAA序列,可以考虑用归纳法证明这一点,也可以随便验算几个例子,显然是正确的。
再看BBB序列,我们发现只需要保证在遍历BBB数组时每次连边都是当前节点向之前的节点连边就一定能够保证这颗树的拓扑序是BBB序列,因为拓扑序的定义是儿子出现在祖先之后,每次向之前的节点连边意味着每个节点都能顺藤摸瓜直捣根节点,这个特点简单来说就是每个节点(除了第一个节点)都会有一条边连向位置更小的节点。
结合AAA序列和BBB序列各自需要满足的特性,我们发现只需要遍历AAA序列,每次都让当前节点uuu连向的节点vvv满足 vvv或uuu在B数组中的位置是当前遍历的所有点中最小的点(拓扑序性质) 以及 vvv是最后加上的一条边的一个端点。假设我们这次连上了u?vu-vu?v这条边,那么比较一下uuu,vvv节点在BBB中谁位置更小,假设是vvv节点,那么下次遇到www节点我们自然地连接w?vw-vw?v边,同理还需要比较www和vvv在BBB数组中的位置大小来决定谁具有与下个节点连边的优先权,这样我们保证每次都是跟已遍历的节点中位置最小的节点相连接,由于BBB数组中每个节点都被遍历到一遍,故每个节点都一定会跟位置比它小的节点相连接(除了第一个节点),满足拓扑序的性质,同时每次连接的点都是上次连接的边的某一个端点,满足dfsdfsdfs序性质,故这种建树方式是可靠地。
此外我们还发现本题只会输出YES,因为这种建图方式显然没有反例存在。
int n,pos[maxn];int main(){
n=rd();FOR(i,1,n+1)pos[rd()]=i;int b=rd(),pre=b;wrsn("YES");FOR(i,0,n-1){
b=rd();wr(b),wrs(" "),wrn(pre);if(!pre || pos[pre]>pos[b])pre=b;}
}