【bzoj3065】带插入区间K小值

2014年9月30日6,28414

Description

从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i]。跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴。这时跳蚤国王决定理性愉悦一下,查询区间k小值。他每次向它的随从伏特提出这样的问题: 从左往右第x个到第y个跳蚤中,a[i]第k小的值是多少。
这可难不倒伏特,他在脑袋里使用函数式线段树前缀和的方法水掉了跳蚤国王的询问。
这时伏特发现有些跳蚤跳久了弹跳力会有变化,有的会增大,有的会减少。
这可难不倒伏特,他在脑袋里使用树状数组套线段树的方法水掉了跳蚤国王的询问。(orz 主席树)
这时伏特发现有些迟到的跳蚤会插入到这一行的某个位置上,他感到非常生气,因为……他不会做了。
请你帮一帮伏特吧。
快捷版题意:带插入、修改的区间k小值在线查询。

Input

第一行一个正整数n,表示原来有n只跳蚤排成一行做早操。
第二行有n个用空格隔开的非负整数,从左至右代表每只跳蚤的弹跳力。
第三行一个正整数q,表示下面有多少个操作。
下面一共q行,一共三种操作对原序列的操作:(假设此时一共m只跳蚤)
1. Q x y k: 询问从左至右第x只跳蚤到从左至右第y只跳蚤中,弹跳力第k小的跳蚤的弹跳力是多少。
(1 <= x <= y <= m, 1 <= k <= y – x + 1)
2. M x val: 将从左至右第x只跳蚤的弹跳力改为val。
(1 <= x <= m)
3. I x val: 在从左至右第x只跳蚤的前面插入一只弹跳力为val的跳蚤。即插入后从左至右第x只跳蚤是我刚插入的跳蚤。
(1 <= x <= m + 1)

为了体现在线操作,设lastAns为上一次查询的时候程序输出的结果,如果之前没有查询过,则lastAns = 0。
则输入的时候实际是:
Q _x _y _k ——> 表示 Q _x^lastAns _y^lastAns _k^lastAns
M _x _val  ——> 表示 M _x^lastAns _val^lastAns
I _x _val  ——> 表示 I _x^lastAns _val^lastAns
简单来说就是操作中输入的整数都要异或上一次询问的结果进行解码。

(祝Pascal的同学早日转C++,就不提供pascal版的描述了。)

Output

对于每个询问输出回答,每行一个回答。

Sample Input

10
10 5 8 28 0 19 2 31 1 22
30
I 6 9
M 1 11
I 8 17
M 1 31
M 6 26
Q 2 7 6
I 23 30
M 31 7
I 22 27
M 26 18
Q 26 17 31
I 5 2
I 18 13
Q 3 3 3
I 27 19
Q 23 23 30
Q 5 13 5
I 3 0
M 15 27
Q 0 28 13
Q 3 29 11
M 2 8
Q 12 5 7
I 30 19
M 11 19
Q 17 8 29
M 29 4
Q 3 0 12
I 7 18
M 29 27

Sample Output

28
2
31
0
14
15
14
27
15
14

HINT

此题作为一个小小的研究来搞吧~做法有很多~不知道这题究竟有多少种做法。
请自觉O(log^2n),我故意卡块状链表,块链A了的请受我深情一拜……
A掉的同学请在Discuss里面简要说下自己的做法吧~
原序列长度 <= 35000
插入个数 <= 35000,修改个数 <= 70000,查询个数 <= 70000  ,0 <= 每时每刻的权值 <= 70000
由于是OJ上的题,所以数据无梯度。为了防止卡OJ,本题只有4组数据。

题解

学习了一下替罪羊树,具体参见WJMZBMR《重量平衡树和后缀平衡树在信息学奥赛中的应用》

替罪羊树是一种不用旋转的平衡树,若一棵子树的左或右子树大小超过其大小55%-80%则暴力重构这棵子树,以此来维护平衡性,每个结点的期望重构次数是logn,实现可以自己脑补一下

在替罪羊树每个结点放一棵包含该子树所有结点的权值线段树,也就是平衡树套权值线段树

1、由于外层是平衡树,那么就能实现插入一个结点:找到它的位置,在根到其路径上所有结点的线段树中插入这个值

2、查询区间第K大:找到这个区间包含若干棵子树,拿出他们的根的权值线段树,一起做个二分

3、修改与插入类似

4、当外层平衡树失衡的时候重构之,将某个子树自下而上线段树合并

然后就是考验数据结构的能力了QAQ

由于内存不够,我们还需要回收垃圾,即对数组的重复使用

写的时候遇到了点麻烦,重构的时候我所有结点暴力插入了,所以我的复杂度是qlog^3n,否则应是qlog^2n

代码略长

 

 

  • sqd2015年7月9日 下午7:59 回复

    蒟蒻求(稍微详一点点, 就一点点嘛, 至少给个搜索关键字嘛)解Orz

    #1  
    • hzwer2015年12月12日 下午2:37 回复
      admin

      0.0 之前没看到。。。我补充了一些

      #11
  • hzwer2015年12月12日 下午2:37 回复
    admin

    QAQ

    #2  
  • wu2016年1月29日 上午11:46 回复

    if(a[rt[k]].sum*alpha>max(a[rt[ls[k]]].sum,a[rt[rs[k]]].sum))这是为什么呢

    #3  
    • hzwer2016年1月30日 上午1:01 回复
      admin

      这是判断平衡树的某个子树是否失去平衡

      #31
  • O(n!)2016年1月29日 下午12:19 回复

    黄学长,请问这个代码为什么是log三方的呢?log方的怎么改呢?

    #4  
  • 何肥2016年3月2日 下午10:59 回复

    黄学长好,我是HN的hf,求问还有其他的做法么??

    #5  
    • 肚子2016年3月2日 下午11:02 回复

      貌似还可以treap套线段树吧。。。你可以去参考vfk的博客。。。

      #51