题目链接:点击查看
题目大意:给出由 n 个数的数列,再给出 m 次查询,每次查询需要输出 [ l , r ] 内小于等于 h 的数有多少个
题目分析:大晚上睡不着觉随便做做题,发现这个题目原来可以用主席树来做,又发现这个题目去年暑假竟然没写博客,于是补上一发
线段树离线的做法就是对数列和询问的高度排序,遍历每个询问,双指针将小于等于当前询问高度的位置都扔到线段树中,记录当前询问的区间内有多少个数即可
主席树在线做法,有两种,先说一下网上最常见的,就是遍历每个位置作为下标,对于下标维护可持久化线段树,每个权值线段树维护的是高度信息,记录一下每个高度出现了多少次,答案显然就是第 R 个版本中 [ 1 , h ] 的个数减去第 L - 1 个版本中 [ 1 , h ] 的个数了
再说一下我自己的做法,我是对于高度维护了可持久化线段树,每个权值线段树维护的是区间信息,记录一下 [ 1 , h ] 内的所有数在区间上的分布情况,这样答案就是第 h 个版本的权值线段树中 [ l , r ] 中有多少个数了
两种主席树的做法时空复杂度相同且都是需要进行离散化的,但我个人感觉自己的做法更好理解一些,更能体现了:主席树是可持久化线段树,其中每个版本的主席树单独拿出来都是一个权值线段树
代码:
主席树:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
离线+线段树:
#include
#include
#include
#include
#include
#include
#include
#include