[codeforces 1208D] Restore Permutation(线段树)
题面
题意:
一个长度为$n$的排列$a$,现在定义$p_i$为数组$a$中x下标小于等于$i$并且小于$a_i$的数字的和。现在给定$p$,求$a$。
思路:
首先可以肯定的是,$p$中最后一个$0$出现的位置$pos$在$a$中一定是$1$。我们可以反证:
假设$a_{pos}$不为$1$,假设$1$在$pos$之前,那么$p_{pos} \ge 1$;假设$1$在$pos$之后,那么$pos$一定不是最后一个$0$出现的位置,因为当$a_{pos}=1$,那么$p_{pos}$一定等于$0$,因此最后一个$0$出现的位置一定是$1$,那么我们把$1$放到$pos$处。并且把$i$之后的$p_{j}$都减去$1$.
其实对于从$2$到$n$的处理方法都一样,对于第$i$次操作,找到$p$中最后一个为$0$的位置$pos$,令$a_{pos}$为$i$,然后对于所有的$i \ge pos$,让$p_{i}-i$。最终即可得到$a$数组。对于上面的操作,可以用线段树。
线段树寻找最后一个$0$的位置:从根节点出发,先看右子树的最小值是否为$0$,如果是,去查右子树,否则查左子树。
最终复杂度$O(n \cdot (log(n))^2)$
代码:
1 |
|