1.hdu5919
题意:给一个序列,每次询问
[
l
,
r
]
[l,r]
[l,r]中,每个数第一次出现时的下标的中位数。
思考:这道题首先需要判断一个区间内出现了多少个不同的数。
对于这个问题,我们考虑记录每个数最后出现的位置,那么,满足最后出现位置在
[
l
,
r
]
[l,r]
[l,r]之间的数的个数就是答案。
但是,这样得出来的结果是
[
l
,
r
]
[l,r]
[l,r]中,每个数最后出现的位置,要想得到最先出现的位置,需要想办法。怎么做?倒过来加入序列,此时的最后位置(倒序列)就是最前位置(正序列)。
然后就是区间中位数(其实就是区间第k大),这里只需要用主席树维护一下每个下标有多少个不同的数最后一次在这里出现,然后查询一下区间第k大的下标就可以做了。
2.cf div716D
题意:给定一个序列,每次询问一个区间
[
l
,
r
]
[l,r]
[l,r],能拆分成多少区间,使得每个区间出现次数最多的数不超过(区间长度记为L)(L+1)/2。
思考:这个需要处理的问题是怎么统计区间内某个数出现多少次。
对于这个问题,我们考虑用vector对每个数都存放他们出现位置的下标,然后用两个lower_bound/upper_bound去查找在这段区间的个数。
详细做法见我另一篇博客传送门
3.ICPC Kunming M Stones
题意:给定一个序列,询问
[
l
,
r
]
[l,r]
[l,r]区间最小的不能被组合出来的数是多少(组合是每个数可以选,可以不选,然后其和就是组合出来的数)
思考:对于首先的一段连续区间
[
1
,
x
]
[1, x]
[1,x]能表示出来,那么如果
x
+
1
x +1
x+1在序列中(或者可以被表示出来),那么
[
1
,
2
∗
x
+
1
]
[1, 2*x +1]
[1,2∗x+1]都可以表示出来。然后继续这个过程。
首先用可持久化线段树维护区间历史信息,然后每次对于已经能确定的区间内
[
1
,
x
]
[1,x]
[1,x],在线段树中查询
<
=
x
+
1
<=x+1
<=x+1的数的和,假设为
y
y
y,那么肯定能将
[
1
,
y
]
[1,y]
[1,y]都表示出来。如果
y
=
x
y=x
y=x,那么就不存在表示方法能表示出
x
+
1
x + 1
x+1,那么就可以直接结束了。
这种做法,每次至少增加
2
2
2倍,复杂度小于
l
o
g
log
log。