POJ 2828 -- Buy Tickets 线段树


POJ 2828 -- Buy Tickets 线段树
Description
Railway tickets were difficult to buy around the Lunar New Year in China, so we must get up early and join a long queue…
The Lunar New Year was approaching, but unluckily the Little Cat still had schedules going here and there. Now, he had to travel by train to Mianyang, Sichuan Province for the winter camp selection of the national team of Olympiad in Informatics.
It was one o’clock a.m. and dark outside. Chill wind from the northwest did not scare off the people in the queue. The cold night gave the Little Cat a shiver. Why not find a problem to think about? That was none the less better than freezing to death!
People kept jumping the queue. Since it was too dark around, such moves would not be discovered even by the people adjacent to the queue-jumpers. “If every person in the queue is assigned an integral value and all the information about those who have jumped the queue and where they stand after queue-jumping is given, can I find out the final order of people in the queue?” Thought the Little Cat.
Input
There will be several test cases in the input. Each test case consists of N + 1 lines where N (1 ≤ N ≤ 200,000) is given in the first line of the test case. The next N lines contain the pairs of values Posi andVali in the increasing order of i (1 ≤ i ≤ N). For each i, the ranges and meanings of Posi and Vali are as follows:
  • Posi ∈ [0, i − 1] — The i-th person came to the queue and stood right behind the Posi-th person in the queue. The booking office was considered the 0th person and the person at the front of the queue was considered the first person in the queue.
  • Vali ∈ [0, 32767] — The i-th person was assigned the value Vali.
There no blank lines between test cases. Proceed to the end of input.
Output
For each test cases, output a single line of space-separated integers which are the values of people in the order they stand in the queue.
Sample Input
4
0 77
1 51
1 33
2 69
4
0 20523
1 19243
1 3890
0 31492
Sample Output
77 33 69 51
31492 20523 3890 19243
Hint
The figure below shows how the Little Cat found out the final order of people in the queue described in the first test case of the sample input.


题目大意:给定n个人进入队伍时的位置,如果某个位置及其后面有人,则后面的人都要向后挪一个位置,这不正是每天都在现实生活中上演的插队问题吗!有n个pos[i]和val[i],pos[i]表示这个人插入到pos[i]的右面,其实加1的话,更好理解,就是插在什么位置。至于那个val[i]只是为了表示某个人而已,理解成RP什么的都可以


是一个逆向思维的运用。
思路:
1 要从后面往前更新线段树
2 线段树记录的是当前区间还剩下多少个记录空间
3 因为后面的插入会使得前面的插入往后退,那么前面插入的下标如果大于前面可以插入的空间,就需要往后退了。
好难理解的操作。仔细观察一下下面update这个函数吧。
二分地去查找适合的插入位置,把插入操作时间效率提高到 O(lgn),如果使用一般方法插入操作效率就会达到O(n)。
http://shoutmon.com/poj-2828.html
注意到后面的总是可以把前面的覆盖掉,所以考虑总是先确定后面的人的位置,这样题目给出的位置pos就变成了“寻找一个位置,使得这个位置左边的空位置数目为pos”,以第一个样例为例:

把样例倒过来之后是这样的:
2 69
1 33
1 51
0 77

先考虑69号,它的pos是2,说明它插入的时候需要队伍前面有2个人,这样,它就在2号位置上了(从0开始)


再考虑33号,它的pos是1,说明它插入的时候需要队伍前面有1个人,这样,它就在1号位置上了;


再考虑51号,它的pos是1,说明它插入的时候需要队伍前面有1个人,这样,它就在3号位置上了;


再考虑77号,它的pos是0,说明它插入的时候需要队伍前面有0个人,这样,它就在0号位置上了。


最后一个人往前插,这样pos的意义就变成了,前面有多少个空位。线段树上每个节点中存储的是当前时刻,该区间有多少空位

嗯,所以开一个empty数组,结点p表示[l,r]区间内的空位置的数目。

不需要query函数,只需要update函数更新就行。

更新到底是往左子树更新还是右子树更新的原则是:当前需要的空位置数x如果小于[l,mid]区间的空位置数(不包含等于),就往左子树搜(rt<<1),否则往右子树搜(往右子树搜的时候要注意参数x应该减去左子树的空位置数,也就是变为x-empty[rt<<1])。(稍微想想应该可以明白的!)

当递归到l==r的时候,说明找到了需要插入的位置,于是将该点的empty减一(要记得Push上来),然后令ans[l]存放插进去的人的val标号。

这个是单点更新,但是这个跟普通的单点更新不一样,普通的单点更新是直接给出了要更新的点的index,但是这个没有直接给出,但是却可以通过empty数组间接求出来。这其实跟树状数组二分tree[]数组找满足条件的点的题目是一样的,这里也是根据empty数组找满足条件(空位置数恰好满足需要)的点,所以可以放在一起考虑一下。

Note: 更新的时候要注意x<empty[mid]的写法是错误的,因为mid仅是index,而不是线段树的标号,应该写成x<empty[rt<<1]。
http://blog.sina.com.cn/s/blog_6635898a0100q16r.html
struct{
    int l, r, w;
}node[3*MAX];
int id, pos[MAX], val[MAX], ans[MAX];
void BuildTree(int left, int right, int u){
    node[u].l = left;
    node[u].r = right;
    node[u].w = right - left + 1;         //  w记录这个区间有多少的空位。
    if(left < right){
        BuildTree(left, (left+right)>>1, u<<1);
        BuildTree(((left+right)>>1)+1, right, (u<<1)+1);
    }
}
void updata(int pos, int u){
    node[u].w --;                         //  这个区间增加了一人,区间空位-1。
    if(node[u].l == node[u].r){
        id = node[u].l; return;
    }
    if(node[u<<1].w >= pos) updata(pos, u<<1);
    else{
        pos -= node[u<<1].w;
        updata(pos, (u<<1)+1);
    }
}
int main(){
    int n, i;
    while(scanf("%d", &n) != EOF){
        BuildTree(1, n, 1);
        for(i = 1; i <= n; i ++)
            scanf("%d%d", &pos[i], &val[i]);
        for(i = n; i >= 1; i --){
            updata(pos[i]+1, 1);
            ans[id] = val[i];
        }
        for(i = 1; i <= n; i ++)
            printf("%d ", ans[i]);
        printf("\n");
    }
    return 0;
}
http://www.cnblogs.com/rayn1027/p/3731925.html
12 int pos[MAX], val[MAX], ans[MAX];
13 int tree[MAX*3], index;
14 
15 void Build(int k, int l, int r)
16 {
17     tree[k] = r - l + 1;    //开始时每个节点都有空位
18     if(l == r)
19         return ;
20     int mid = (l + r) >> 1;
21     Build(k<<1, l, mid);
22     Build(k<<1|1, mid+1, r);
23 }
24 void Update(int k, int l, int r, int pos)
25 {
26     tree[k]--;  //单点更新,减少一个空位
27     if(l == r)
28     {
29         index = l;
30         return ;
31     }
32     int mid = (l + r) >> 1;
33     if(tree[k<<1] >= pos)   //如果当前位置的左边空位够的话就落在左边
34     {
35         Update(k<<1, l, mid, pos);
36     }
37     else
38     {
39         pos -= tree[k<<1];  //否则,就把左边的空位减去,再在右边定位
40         Update(k<<1|1, mid+1, r, pos);
41     }
42 }
43 int main()
44 {
45 #ifdef _Rayn
46     freopen("in.txt", "r",stdin);
47 #endif
48     int n;
49     while(scanf("%d", &n) != EOF)
50     {
51         Build(1, 1, n);
52         for(int i=1; i<=n; ++i)
53         {
54             scanf("%d%d", &pos[i], &val[i]);
55         }
56         for(int i=n; i>=1; --i)
57         {
58             Update(1, 1, n, pos[i]+1);
59             ans[index] = val[i];
60         }
61         for(int i=1; i<=n; ++i)
62         {
63             printf("%d%c", ans[i], (i == n)? '\n':' ');
64         }
65     }
66     return 0;
67 }
Also check http://www.cnblogs.com/rayn1027/p/3731925.html
Read full article from 2828 -- Buy Tickets

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