01排序问题
特征:要钦定某个数判断是否符合什么条件;只跟相对大小有关。尤其是中位数、第几位上的数是谁。
[CQOI2009] 中位数
给出 \(1,2,...,n\) 的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是 \(b\)。
Solution:¶
中位数,只跟相对大小有关,改变原序列:把大于 \(b\) 的数全部变为 \(1\),小于 \(b\) 的数变为 \(-1\),等于 \(b\) 则为 \(0\) 。
问题就变为求存在几个包含 \(b\) 的区间和为 \(0\) 。我们假设 \(tmp\) 为 \(b\) 的下标,原数组为 \(x\),新数组为 \(a\) 。
Example:¶
1 2 |
|
能使结果成立的区间分别为 \([1,5]\) , \([1,7]\) , \([2,4]\) , \([4,4]\)。
预处理出 \(tmp\) 左边的后缀和与右边的前缀和,开两个桶 \(l,r\) ,分别计数 \(tmp\) 左右两边前缀和的值的出现次数。于是左边的 \(l[x]\) 可以与右边的每一个 \(r[-x]\) 进行匹配。通过乘法原理,该值即为 \(l[x] \times r[-x]\),由题意可知 \(-10^5 \le x \le 10^5\),遍历所有的 \(x\) 即可,最终答案为 \(\sum_{i=min}^{max}l[i] \times r[-i]\) 。
值得注意的是,\(l[0]\) 和 \(r[0]\) 的初始值为 \(1\),因为 \(b\) 是需要被算入的。当然,桶的下标不能是负数,所以我在每次操作时都加上了一个很大的数,即数据最大值 —— \(10^5\),也可以用 \(STL\) 中的 \(map\) 解决问题,时间复杂度为 \(O(n)\) 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
P2824 [HEOI2016/TJOI2016] 排序
给出一个 1 到 n 的排列,现在对这个排列序列进行 m 次局部排序,排序分为两种:
0 l r
表示将区间 \([l,r]\) 的数字升序排序1 l r
表示将区间 \([l,r]\) 的数字降序排序
最后询问第 \(q\) 位置上的数字。
Solution:¶
线段树01排序 \(O(\log n)\) +二分答案
二分一个数 \(x\), 将大于等于 \(x\) 的数设为1,小于 \(x\) 的数设为0,用线段树跑出所有的操作,共 \(O(m\log n)\)。若此时最后第 \(q\) 位是1,说明答案一定大于等于这个数,否则则一定比这个数小。故二分边界 \(l=1,r=n+1\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|