2023大厂真题提交网址(含题解):
www.CodeFun2000.com(http://101.43.147.120/)
最近我们一直在将收集到的机试真题制作数据并搬运到自己的OJ上,供大家免费练习,体会真题难度。现在OJ已录入50+道2023年最新大厂真题,同时在不断的更新。同时,可以关注"塔子哥学算法"公众号获得每道题的题解。
题目大意
给你一个长度为 n n n的排列。然后给 m m m次操作。每次对一个区间升序排序/降序排序。问最后第p个位置是多少?
方法一:二分答案+线段树(思维)
核心:对数字排序太慢了。但是对01串排序却可以高效的使用线段树来实现
那么我们可以二分答案,令答案在 [ m i d , n ] [mid,n] [mid,n]区间里。将值域在该区间里的数变为1,其他变为0。那么线段树模拟一遍,然后 c h e c k check check一下位置p是否为1.这么二分即可。
复杂度: O ( m l o g n l o g n ) O(mlognlogn) O(mlognlogn)
方法二:set+动态开点权值线段树分裂合并
核心:
1.我们用一个权值线段树来维护/表征 一个有序的区间.那么最开始就有 n n n个有序段.
2.每次排序操作,等同于将若干个有序区间合并.而且最多可能会在左右端点处将两个有序区间分裂开.
3.我们规定将一个有序区间(一个权值线段树)的根记到该区间的最左位置。
例如: [4 5 6] [3 2 1] [7]
那么整个序列有三颗线段树,三个根分别为{1,4,7} (数值代表下标).
4.具体操作示范:
如果现在我需要重新升序排序区间[2,5]
1.那么先快速找到下标2的根:1,再快速找到下标5的根:4
2.将树rt[1]和rt[4]分裂成: [4] [5 6] [3 2] [1][7]
3.将树rt[1]到rt[4]之间所有根合并到一棵权值线段树上:
[4][2 3 5 6][1][7]
PS:
1.上述找根过程可以使用set+二分来优化
2.由于权值线段树本身有序,所以使用一个标记来表征该有序区间是升序还是降序.
复杂度
时间复杂度:
1步骤的复杂度为: O ( l o g n ) O(logn) O(logn)
2步骤的复杂度为: O ( l o g n ) O(logn) O(logn)
3步骤的复杂度为:
就是将所有树合并成一棵树的复杂度?,大概为 m l o g n mlogn mlogn
所以总复杂度为: O ( ( n + m ) l o g n ) O((n+m)logn) O((n+m)logn)?
空间复杂度:
方法对比
方法一:
好处:
可以解决有值重复的问题
坏处:
无法查询最终数组状态,只能查询某个位置
方法二:
坏处:不支持值重复.
好处:可以高效模拟整个过程.可以获得数组最终状态.
PS:set如果换成线段树维护,好像可以支持在线查询区间和等性质&#