从区间第K大讲起
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

从区间第K大讲起

on

  • 866 views

在学校自娱自乐的作品。讲了2题:...

在学校自娱自乐的作品。讲了2题:
区间第k大,在线,无修改
区间第k大,在线,有修改


介绍几种方法:
归并树(无修改)
划分树(无修改)
树套树(线段树套平衡树,有修改)
块状数组(有修改)
可持久化线段树(无修改)


有一些错误,比如说树套树的修改复杂度是:O(2*log^2n)

http://quartergeek.com/lecture-kth-number

Statistics

Views

Total Views
866
Views on SlideShare
701
Embed Views
165

Actions

Likes
0
Downloads
1
Comments
0

1 Embed 165

http://quartergeek.com 165

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

从区间第K大讲起 Presentation Transcript

  • 1. 从区间第K大讲起归并树 划分树 树套树 块状数组可持久化线段树
  • 2. 约定 根据汉语口语的一些性质,以及不要在意细节, 以及第k大和第k小本质相同,下面约定: 区间第k大 意为 区间第k小
  • 3. Problem 1: 在线 无修改复杂度要求:空间 :O(n*logn)预处理时间 :O(n*logn)单次查询时间 :O(log3n)归并树可以解决
  • 4.  二分答案,将问题转化为判定性问题 在已知答案ans的情况下,计算ans在所求区间 的Rank,根据Rank与k的关系,缩紧二分区间 如何判定ans在所求区间的Rank?
  • 5.  按照归并排序建树,sum[deep][i]记录当前 深度下i所在区间中,前i-l个数中有多少个分 到了左子树当中 即有多少数比排序完的a[mid]小
  • 6.  求Rank的时候分别计算在左右两棵子树当中的 Rank,然后再合并,就是所求Rank 怎么求ans在某个区间的rank? 二分!
  • 7.  Find(p, deep, value) //每组调用logn次 if SegmentTree[p]为叶子节点 return lower_bound(lef, rig, value)-lef //O(logn) res = 0 res += Find(p*2, deep+1, value) res += Find(p*2+1, deep+1, value) return res Main lef = min{a[i]}, rig = max{a[i]} while (lef+1 < rig) //计算logn组 mid = (lef+rig)/2 if Find(1, 1, mid) >= k rig = mid else lef = mid
  • 8.  二分答案 O(logn) 在线段树中操作 O(logn) 每个线段树叶子节点中确定Rank O(logn) 单次查询 O(log3n)
  • 9. Problem 2: 在线 无修改 无相同数复杂度要求:空间 :O(n*logn)预处理时间 :O(n*logn)单次查询时间 :O(logn)划分树可以解决
  • 10.  sum[deep][i]记录对于每个区间[l, r]的 前i-l+1项中,合并时有多少个数归到左边 即有多少数比排序完的a[mid]小 最多有log(n)层 每次查询线段树区间[l, r]第k大时,根据 sum[deep][i]调整,递归解决
  • 11.  查询[2, 7]的第3大 sorted[] [1 2 3 4 5 6 7 8] a[0] [4 2 7 1 5 6 8 3] a[1] [4 2 1 3][7 5 6 8] a[2] [2 1][4 3][5 6][7 8] a[3] [1][2][3][4][5][6][7][8]
  • 12.  Query(deep, st, ed, lef, rig, k) 深度 :deep 线段树区间 :[st, ed] 查询区间 :[lef, rig] 查询第k大
  • 13.  Query(deep, st, ed, lef, rig, k) if (lef == rig) return a[deep][lef] CountLef = sum[deep][lef-1] CountRig = sum[deep][rig] if (CountRig-CountLef >= k) //左边的个数多于k个,答案在左边 return Query(deep+1, st, mid, CountLef+st, st+CountRig-1, k) else //否则就在右边查找第k-(CountLef-CountRig)大 return Query(deep+1, mid+1, ed, mid+1+lef-st-CountLef, mid+1+rig-st-CountRig, k-(Countlef-CountRig)) st lef rig ed [ [ ] ] |-CountLef-| |------CountRig-----|
  • 14. PKU2104 Accepted 14900K 1094MS G++
  • 15. Problem 1: 在线 无修改 有相同数 Sol2复杂度要求:空间 :O(n*logn)预处理时间 :O(n*logn)单次查询时间 :O(logn)划分树可以解决
  • 16.  我发现原来写的划分树有问题,遇到重复的数 就挂掉了 HDU2665 RE! 讨论下
  • 17. Problem 3: 在线 有修改复杂度要求:空间 :O(n*logn)预处理时间 :O(n*logn)单次修改时间 :O(log2n)单次查询时间 :O(log3n)树套树!
  • 18.  线段树能够完成对区间的限制 平衡树能够完成统计区间上不大于k的数 线段树套平衡树!
  • 19.  每一个线段树的节点为一棵平衡树 显然叶子节点的每一棵平衡树只有一个节点 对于线段树非叶子节点,保存所有叶子节点平 衡树的并
  • 20.  修改:从线段树根进去,递归处理 每一棵子树,都要从它的平衡树中把待修改节 点的旧值删去 然后用同样的方法添加新值 O(2*logn)
  • 21.  查询:二分答案,计算在区间内的Rank 如何计算Rank? 平衡树中每个节点记下当前节点为根的子树有 多少节点 平衡树旋转的时候重新统计节点数量 查询时根据平衡树的性质向两边递归查找
  • 22.  Hint:平衡树重复节点的处理方法:可以在每 个节点中添加属性Count,保存有几个相同节 点 删除时Count-1,如果Count=0,再合并子树
  • 23.  Rank(BSTNode, ToRank) if BSTNode为空 return 0 if (ToRank < BSTNode.Value) //查询的比当前节点小,递归左子树 return Rank(BSTNode.LeftChild, ToRank) else return Rank(BSTNode.RightChild, ToRank) //同上处理右子树 + BSTNode.Count //当前节点的个数 + BSTNode.LeftChild.Size //左子树中的数一定比它小
  • 24.  二分答案 O(logn) 线段树中操作 O(logn) 递归处理平衡树 O(logn) 单次查询 O(log3n) 单次插入删除 O(log2n) 预处理相当于n次插入 O(nlogn) 线段树常数略大,考虑用树状数组实现
  • 25. Accepted ZJU2112 C++ 3040MS 19320KBBZOJ1901 Accepted 4172 kb 1244 ms C++
  • 26. Problem 3: 在线 有修改 Sol2
  • 27. 
  • 28.  初始化:将数据放入块状数组中,排序每个块 修改:确定修改的数所在块状数组中的位置, 直接修改,然后暴力重新排序当前块 查询:二分答案,查询答案在块状数组中的 Rank
  • 29. 
  • 30. Accepted ZJU2112 C++ 4770ms 572kbBZOJ1901 Accepted 884 kb 1264 ms C++
  • 31. 说好的可持久化数据结构呢?
  • 32. Problem 1: 在线 无修改 Sol 3复杂度要求:空间 :O(4n+nlogn)预处理时间 :O(nlogn)单次查询时间 :O(logn)可持久化线段树!
  • 33. History Version 1
  • 34. History Version 2
  • 35.  A[] 1 5 2 6 3 7 4 按权值建线段树: 线段树版本 1 2 3 4 5 6 7 0 1 +1 2 +1 +1 3 +1 +1 +1 4 +1 +1 +1 +1 5 +1 +1 +1 +1 +1 6 +1 +1 +1 +1 +1 +1 7 +1 +1 +1 +1 +1 +1 +1
  • 36.  查询[2, 5]的第3大 A[] 1 5 2 6 3 7 4 线段树版本 1 2 3 4 5 6 7 0 1 +1 2 +1 +1 3 +1 +1 +1 4 +1 +1 +1 +1 5 +1 +1 +1 +1 +1 6 +1 +1 +1 +1 +1 +1 7 +1 +1 +1 +1 +1 +1 +1 5-(2-1) +1 +1 +1 +1
  • 37. 
  • 38. PKU2104 Accepted 26884K 2047MS G++
  • 39. Problem 3: 在线 有修改 Sol3复杂度要求:空间 :O(???)预处理时间 :O(???)单次修改时间 :O(???)单次查询时间 :O(???)可持久化线段树!
  • 40.  大表说他不会!
  • 41. Thanks: Orz 云南 Orz 大表 Orz 小胖