POJ 2828 Buy Tickets (线段树 or 树状数组+二分)

Posted Recoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2828 Buy Tickets (线段树 or 树状数组+二分)相关的知识,希望对你有一定的参考价值。

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

题意就是给你n个人,然后每个人按顺序插队,问你最终的顺序是怎么样的。

反过来做就很容易了,从最后一个人开始推,最后一个人位置很容易就确定了,那最后第二个人的位置也可以推(与最后一个人的位置无关)...依次就都可以确定所有的人了。

用前缀和的思想,要是这个人的位置确定了,那么就标记这个人位置的值为0,然后回溯更新,跟求逆序对个数的思想比较类似。

线段树:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int MAXN = 2e5 + 5;
 6 struct segtree {
 7     int l , r , val;
 8 }T[MAXN << 2];
 9 int x[MAXN] , y[MAXN] , ans[MAXN] , id;
10 
11 void init(int p , int l , int r) {
12     T[p].l = l , T[p].r = r;
13     int mid = (l + r) >> 1;
14     if(l == r) {
15         T[p].val = 1;
16         return ;
17     }
18     init(p << 1 , l , mid);
19     init((p << 1)|1 , mid + 1 , r);
20     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
21 }
22 
23 void updata(int p , int num) {
24     int mid = (T[p].l + T[p].r) >> 1;
25     if(T[p].l == T[p].r) {
26         T[p].val = 0;
27         id = T[p].l;
28         return ;
29     }
30     if(num <= T[p << 1].val) {
31         updata(p << 1 , num);
32     }
33     else {
34         updata((p << 1)|1 ,  num - T[p << 1].val);
35     }
36     T[p].val = T[p << 1].val + T[(p << 1)|1].val;
37 }
38 
39 int main()
40 {
41     int n;
42     while(~scanf("%d" , &n)) {
43         init(1 , 1 , n);
44         for(int i = 0 ; i < n ; i++) {
45             scanf("%d %d" , x + i , y + i);
46             x[i]++;
47         }
48         for(int i = n - 1 ; i >= 0 ; i--) {
49             updata(1 , x[i]);
50             ans[id] = y[i];
51         }
52         for(int i = 1 ; i < n ; i++) {
53             printf("%d " , ans[i]);
54         }
55         printf("%d\n" , ans[n]);
56     }
57 }

树状数组+二分:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int MAXN = 2e5 + 5;
 6 int bit[MAXN] , n , x[MAXN] , y[MAXN] , ans[MAXN];
 7 
 8 inline void add(int i , int num) {
 9     for( ; i <= n ; i += (i & -i)) {
10         bit[i] += num;
11     }
12 }
13 
14 int sum(int i) { 
15     int s = 0;
16     for( ; i > 0 ; i -= (i & -i))
17         s += bit[i];
18     return s;
19 }
20 
21 int main()
22 {
23     while(~scanf("%d" , &n)) {
24         memset(bit , 0 , sizeof(bit));
25         for(int i = 1 ; i <= n ; i++) {
26             scanf("%d %d" , x + i , y + i);
27             x[i]++;
28             add(i , 1);
29         }
30         for(int i = n ; i >= 1 ; i--) {
31             int l = 1 , r = n , mid;
32             while(l < r) {
33                 mid = (l + r) >> 1;
34                 if(sum(mid) >= x[i])
35                     r = mid;
36                 else 
37                     l = mid + 1;
38             }
39             ans[l] = y[i];
40             add(l , -1);
41         }
42         for(int i = 1 ; i < n ; i++) {
43             printf("%d " , ans[i]);
44         }
45         printf("%d\n" , ans[n]);
46     }
47 }

 

以上是关于POJ 2828 Buy Tickets (线段树 or 树状数组+二分)的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2828Buy Tickets(线段树的单点维护)

POJ2828Buy Tickets(线段树)

POJ - 2828 Buy Tickets(线段树单点更新)

POJ 2828 Buy Tickets(线段树单点)

POJ 2828 Buy Tickets (线段树 or 树状数组+二分)

Buy Tickets POJ - 2828 思维+线段树