划分树 Partition Tree


http://baike.baidu.com/view/4199603.htm
划分树是一种基于线段树的数据结构。主要用于快速求出(在log(n)的时间复杂度内)序列区间的第k大值。
http://yueyue1105.blog.163.com/blog/static/431117682010716111425892/
同样以1 5 2 6 3 7为例:
根据中位数mid,将区间划分成左子树中的数小于等于mid,右子树中的数大于等于mid,得到这样一棵划分树:
        [1 5 2 6 3 7]
     [1 2 3]      [5 6 7]
   [1 2]  [3]    [5 6] [7]
  [1] [2]        [5] [6] 
注意要保持下标的先后顺序不变
对每一个区间,用sum[i]记录区间的左端点left到i有几个进入了左子树,即有几个数小于等于mid
用对应的下标区间建线段树:(这里下标区间对应的是排序后的数列)
            [1 6]
     [1 3]      [4 6]
  [1 2] [3]   [4 5][6]
  [1][2]      [4][5]
每次查找[l r]区间的第k大数时,先查看当前区间[left right]下的sum[r] - sum[l - 1]是否小于等于k,如果是,则递归到左子树,并继续在[left + sum[l - 1], left + sum[r] - 1]中找第k大数;
否则,进入右子树,继续在[mid + l - left + 1 - sum[l - 1], mid + r - left + 1 - sum[r]]找第k - sum[r] + sum[l - 1]大数
这样一次查询只要logn的复杂度

对于建划分树的方法,我一开始是先建完一层,再往下递归,过了PKU2104后,交HDU2665WA,后来发现对于0 0 -1这样的数据,下一层本应该是-1 0 0,而我的程序还是0 0 -1,原因就是会有很多相同的元素等于mid。于是我就找什么是唯一的,很容易想到数组的下标,仔细观察,如果从划分树叶子回溯,相当于在对数组下标进行归并排序,于是我的问题就解决了~
http://java-mans.iteye.com/blog/1644583
归并树是在建树的过程中保存归并排序。
划分树是在建树的过程中保存快速排序。
其中归并树适合解决一个数在某个区间的名次。
划分树适合解决某个区间的K大数。
POJ这题是找K大数,归并树也可做,二分答案,再由归并树找出这个数的名次。划分树更快。
  1. struct Node{  
  2.     int left,right,mid;  
  3. }tree[N*4];  
  4. int sa[N],num[20][N],cnt[20][N]; //sa中是排序后的,num记录每一层的排序结果,cnt[deep][i]表示第deep层,前i个数中有多少个进入左子树  
  5. int n,q;  
  6. void debug(int d){  
  7.     for(int i=1;i<=n;i++)  
  8.         printf("%d ",num[d][i]);  
  9.     printf("\n");  
  10. }  
  11. void bulid(int step,int l,int r,int deep){  
  12.     tree[step].left=l;  
  13.     tree[step].right=r;  
  14.     tree[step].mid=(l+r)>>1;  
  15.     if(l==r)  
  16.         return;  
  17.     int mid=(l+r)>>1;  
  18.     int mid_val=sa[mid],lsum=mid-l+1;;  
  19.     for(int i=l;i<=r;i++)  
  20.         if(num[deep][i]<mid_val)  
  21.             lsum--;    //lsum表示左子树中还需要多少个中值  
  22.     int L=l,R=mid+1;  
  23.     for(int i=l;i<=r;i++){  
  24.         if(i==l)  
  25.             cnt[deep][i]=0;  
  26.         else  
  27.             cnt[deep][i]=cnt[deep][i-1];  
  28.         if(num[deep][i]<mid_val||(num[deep][i]==mid_val&&lsum>0)){  //左子树  
  29.             num[deep+1][L++]=num[deep][i];  
  30.             cnt[deep][i]++;  
  31.             if(num[deep][i]==mid_val)  
  32.                 lsum--;  
  33.         }  
  34.         else  
  35.             num[deep+1][R++]=num[deep][i];  
  36.     }  
  37. //  debug(deep);  
  38.     bulid(2*step,l,mid,deep+1);  
  39.     bulid(2*step+1,mid+1,r,deep+1);  
  40. }  
  41. int query(int step,int l,int r,int k,int deep){  
  42.     if(l==r)  
  43.         return num[deep][l];  
  44.     int s1,s2;   //s1为[tree[step].left,l-1]中分到左子树的个数  
  45.     if(tree[step].left==l)  
  46.         s1=0;  
  47.     else  
  48.         s1=cnt[deep][l-1];  
  49.     s2=cnt[deep][r]-s1;   //s2为[l,r]中分到左子树的个数  
  50.     if(k<=s2)   //左子树的数量大于k,递归左子树  
  51.         return query(2*step,tree[step].left+s1,tree[step].left+s1+s2-1,k,deep+1);  
  52.     int b1=l-1-tree[step].left+1-s1;  //b1为[tree[step].left,l-1]中分到右子树的个数  
  53.     int b2=r-l+1-s2;   //b2为[l,r]中分到右子树的个数  
  54.     return query(2*step+1,tree[step].mid+1+b1,tree[step].mid+1+b1+b2-1,k-s2,deep+1);  
  55. }  
  56. int main(){;  
  57.     while(scanf("%d%d",&n,&q)!=EOF){          
  58.         for(int i=1;i<=n;i++){  
  59.             scanf("%d",&num[1][i]);  
  60.             sa[i]=num[1][i];  
  61.         }  
  62.         sort(sa+1,sa+n+1);  
  63.         bulid(1,1,n,1);  
  64.         while(q--){  
  65.             int l,r,k;  
  66.             scanf("%d%d%d",&l,&r,&k);  
  67.             printf("%d\n",query(1,l,r,k,1));  
  68.         }  
  69.     }  
  70.     return 0;  
http://sbp810050504.blog.51cto.com/2799422/1008930

https://github.com/zsc1993916/AcmTemplate/blob/master/Datastructure/%E5%88%92%E5%88%86%E6%A0%91%E6%B1%82%E5%8C%BA%E9%97%B4k%E5%A4%A7%E6%95%B0.cpp

http://java-mans.iteye.com/blog/1644582

Labels

LeetCode (1432) GeeksforGeeks (1122) LeetCode - Review (1067) Review (882) Algorithm (668) to-do (609) Classic Algorithm (270) Google Interview (237) Classic Interview (222) Dynamic Programming (220) DP (186) Bit Algorithms (145) POJ (141) Math (137) Tree (132) LeetCode - Phone (129) EPI (122) Cracking Coding Interview (119) DFS (115) Difficult Algorithm (115) Lintcode (115) Different Solutions (110) Smart Algorithm (104) Binary Search (96) BFS (91) HackerRank (90) Binary Tree (86) Hard (79) Two Pointers (78) Stack (76) Company-Facebook (75) BST (72) Graph Algorithm (72) Time Complexity (69) Greedy Algorithm (68) Interval (63) Company - Google (62) Geometry Algorithm (61) Interview Corner (61) LeetCode - Extended (61) Union-Find (60) Trie (58) Advanced Data Structure (56) List (56) Priority Queue (53) Codility (52) ComProGuide (50) LeetCode Hard (50) Matrix (50) Bisection (48) Segment Tree (48) Sliding Window (48) USACO (46) Space Optimization (45) Company-Airbnb (41) Greedy (41) Mathematical Algorithm (41) Tree - Post-Order (41) ACM-ICPC (40) Algorithm Interview (40) Data Structure Design (40) Graph (40) Backtracking (39) Data Structure (39) Jobdu (39) Random (39) Codeforces (38) Knapsack (38) LeetCode - DP (38) Recursive Algorithm (38) String Algorithm (38) TopCoder (38) Sort (37) Introduction to Algorithms (36) Pre-Sort (36) Beauty of Programming (35) Must Known (34) Binary Search Tree (33) Follow Up (33) prismoskills (33) Palindrome (32) Permutation (31) Array (30) Google Code Jam (30) HDU (30) Array O(N) (29) Logic Thinking (29) Monotonic Stack (29) Puzzles (29) Code - Detail (27) Company-Zenefits (27) Microsoft 100 - July (27) Queue (27) Binary Indexed Trees (26) TreeMap (26) to-do-must (26) 1point3acres (25) GeeksQuiz (25) Merge Sort (25) Reverse Thinking (25) hihocoder (25) Company - LinkedIn (24) Hash (24) High Frequency (24) Summary (24) Divide and Conquer (23) Proof (23) Game Theory (22) Topological Sort (22) Lintcode - Review (21) Tree - Modification (21) Algorithm Game (20) CareerCup (20) Company - Twitter (20) DFS + Review (20) DP - Relation (20) Brain Teaser (19) DP - Tree (19) Left and Right Array (19) O(N) (19) Sweep Line (19) UVA (19) DP - Bit Masking (18) LeetCode - Thinking (18) KMP (17) LeetCode - TODO (17) Probabilities (17) Simulation (17) String Search (17) Codercareer (16) Company-Uber (16) Iterator (16) Number (16) O(1) Space (16) Shortest Path (16) itint5 (16) DFS+Cache (15) Dijkstra (15) Euclidean GCD (15) Heap (15) LeetCode - Hard (15) Majority (15) Number Theory (15) Rolling Hash (15) Tree Traversal (15) Brute Force (14) Bucket Sort (14) DP - Knapsack (14) DP - Probability (14) Difficult (14) Fast Power Algorithm (14) Pattern (14) Prefix Sum (14) TreeSet (14) Algorithm Videos (13) Amazon Interview (13) Basic Algorithm (13) Codechef (13) Combination (13) Computational Geometry (13) DP - Digit (13) LCA (13) LeetCode - DFS (13) Linked List (13) Long Increasing Sequence(LIS) (13) Math-Divisible (13) Reservoir Sampling (13) mitbbs (13) Algorithm - How To (12) Company - Microsoft (12) DP - Interval (12) DP - Multiple Relation (12) DP - Relation Optimization (12) LeetCode - Classic (12) Level Order Traversal (12) Prime (12) Pruning (12) Reconstruct Tree (12) Thinking (12) X Sum (12) AOJ (11) Bit Mask (11) Company-Snapchat (11) DP - Space Optimization (11) Dequeue (11) Graph DFS (11) MinMax (11) Miscs (11) Princeton (11) Quick Sort (11) Stack - Tree (11) 尺取法 (11) 挑战程序设计竞赛 (11) Coin Change (10) DFS+Backtracking (10) Facebook Hacker Cup (10) Fast Slow Pointers (10) HackerRank Easy (10) Interval Tree (10) Limited Range (10) Matrix - Traverse (10) Monotone Queue (10) SPOJ (10) Starting Point (10) States (10) Stock (10) Theory (10) Tutorialhorizon (10) Kadane - Extended (9) Mathblog (9) Max-Min Flow (9) Maze (9) Median (9) O(32N) (9) Quick Select (9) Stack Overflow (9) System Design (9) Tree - Conversion (9) Use XOR (9) Book Notes (8) Company-Amazon (8) DFS+BFS (8) DP - States (8) Expression (8) Longest Common Subsequence(LCS) (8) One Pass (8) Quadtrees (8) Traversal Once (8) Trie - Suffix (8) 穷竭搜索 (8) Algorithm Problem List (7) All Sub (7) Catalan Number (7) Cycle (7) DP - Cases (7) Facebook Interview (7) Fibonacci Numbers (7) Flood fill (7) Game Nim (7) Graph BFS (7) HackerRank Difficult (7) Hackerearth (7) Inversion (7) Kadane’s Algorithm (7) Manacher (7) Morris Traversal (7) Multiple Data Structures (7) Normalized Key (7) O(XN) (7) Radix Sort (7) Recursion (7) Sampling (7) Suffix Array (7) Tech-Queries (7) Tree - Serialization (7) Tree DP (7) Trie - Bit (7) 蓝桥杯 (7) Algorithm - Brain Teaser (6) BFS - Priority Queue (6) BFS - Unusual (6) Classic Data Structure Impl (6) DP - 2D (6) DP - Monotone Queue (6) DP - Unusual (6) DP-Space Optimization (6) Dutch Flag (6) How To (6) Interviewstreet (6) Knapsack - MultiplePack (6) Local MinMax (6) MST (6) Minimum Spanning Tree (6) Number - Reach (6) Parentheses (6) Pre-Sum (6) Probability (6) Programming Pearls (6) Rabin-Karp (6) Reverse (6) Scan from right (6) Schedule (6) Stream (6) Subset Sum (6) TSP (6) Xpost (6) n00tc0d3r (6) reddit (6) AI (5) Abbreviation (5) Anagram (5) Art Of Programming-July (5) Assumption (5) Bellman Ford (5) Big Data (5) Code - Solid (5) Code Kata (5) Codility-lessons (5) Coding (5) Company - WMware (5) Convex Hull (5) Crazyforcode (5) DFS - Multiple (5) DFS+DP (5) DP - Multi-Dimension (5) DP-Multiple Relation (5) Eulerian Cycle (5) Graph - Unusual (5) Graph Cycle (5) Hash Strategy (5) Immutability (5) Java (5) LogN (5) Manhattan Distance (5) Matrix Chain Multiplication (5) N Queens (5) Pre-Sort: Index (5) Quick Partition (5) Quora (5) Randomized Algorithms (5) Resources (5) Robot (5) SPFA(Shortest Path Faster Algorithm) (5) Shuffle (5) Sieve of Eratosthenes (5) Strongly Connected Components (5) Subarray Sum (5) Sudoku (5) Suffix Tree (5) Swap (5) Threaded (5) Tree - Creation (5) Warshall Floyd (5) Word Search (5) jiuzhang (5)

Popular Posts