[POJ2828]Buy Tickets(线段树)

题目链接:http://poj.org/problem?id=2828

插队问题,看样例看hits就能理解题意。

难点在于:N≤200,000。插入数据从后往前,线段树节点维护当前空位置数量。

比如第一个样例:

4
0 77
1 51
1 33
2 69

倒着插入,位置分别+1。首先是3 69。在位置3处插入后,此时位置3的父节点[3,4]显示还有1个位置,同层的节点[1,2]显示有两个。此时树根节点[1,4]显示有3个空位。

再插入2 33。插入位置为2。此时树根节点[1,4]显示有2个空位,[1,2]有1个,[3,4]有一个。

问题来了,插入2 51的时候如何调整:因为是倒着插入数据的,那么也就是之前插入的未发生冲突的数字位置是确定不会再移动。下面遇到了需要调整的部分:

因为被后来的人插了队,所以这个节点应该向后错一个位置。所以被调整到了位置4。同理1 77。

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <iomanip>
 4 #include <cstring>
 5 #include <climits>
 6 #include <complex>
 7 #include <fstream>
 8 #include <cassert>
 9 #include <cstdio>
10 #include <cstdlib>
11 #include <bitset>
12 #include <vector>
13 #include <deque>
14 #include <queue>
15 #include <stack>
16 #include <ctime>
17 #include <set>
18 #include <map>
19 #include <cmath>
20 
21 using namespace std;
22 
23 #define lson l, m, rt << 1
24 #define rson m + 1, r, rt << 1 | 1
25 const int maxn = 222222;
26 int st[maxn<<2];
27 int pos[maxn], num[maxn], ans[maxn];
28 
29 void pushUP(int rt) {
30     st[rt] = max(st[rt<<1], st[rt<<1|1]);
31 }
32 
33 void build(int l, int r, int rt) {
34     st[rt] = r - l + 1;
35     if(l == r) {
36         return;
37     }
38     int m = (l + r) >> 1;
39     build(lson);
40     build(rson);
41 }
42 
43 void update(int p, int l, int r, int rt, int& id) {
44     st[rt]--;
45     if(l == r) {
46         id = l;
47         return;
48     }
49     int m = (l + r) >> 1;
50     if(st[rt<<1] >= p) {
51         update(p, lson, id);
52     }
53     else {
54         p -= st[rt<<1];
55         update(p, rson, id);
56     }
57 }
58 
59 int main() {
60     // freopen("in", "r", stdin);
61     int n;
62     while(~scanf("%d", &n)) {
63         build(1, n, 1);
64         for(int i = 1; i <= n; i++) {
65             scanf("%d %d", &pos[i], &num[i]);
66         }
67         int id = 0;
68         for(int i = n; i >= 1; i--) {
69             update(pos[i]+1, 1, n, 1, id);
70             ans[id] = num[i];
71         }
72         for(int i = 1; i <= n; i++) {
73             printf("%d ", ans[i]);
74         }
75         printf("\n");
76     }
77     return 0;
78 }

 

你可能感兴趣的:([POJ2828]Buy Tickets(线段树))