• 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
    " , 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
    " , ans[n]);
    46     }
    47 }
  • 相关阅读:
    交换函数swap的三种实现方法
    oracle如何修改某一列的数据类型
    安装 kibana 以及添加中文分词器
    linux 安装Elasticsearch
    docker添加tomcat容器成功无法访问首页
    docker run-it centos提示FATAL
    启动、重新启动容器后,进入交互模式
    获取阿里云docker加速器地址
    CentOS6 修改默认字符集为GBK
    linux中如何查看redis的版本
  • 原文地址:https://www.cnblogs.com/Recoder/p/5352277.html
Copyright © 2020-2023  润新知