zoukankan      html  css  js  c++  java
  • POJ 2828 Buy Tickets(单点更新) 详细题解和思路

    题意:给n个人插队,输出最后的队伍情况(题意写的有些粗糙)

    思路:第一点:在最后的队伍中,我们唯一能确定的是最后一个人一定能排到指定位置。那么,倒数第二个是在最后一个基础上确定位置的,这样一层一层的倒着确定,所以,我们要逆着放,用二分的方法。

       第二点:将一个插队问题与线段树所所解决的问题进行联系:插到第k个位置也就是前面要留k(0也是一个)个位置(我们先不管这个位置是有有人)那么,是不是将k转化为前面有多少空位子。

         那插这样两个数据呢?  

        eg: 2  5

           2  6

    就是先优先在二分的前面一段找是否有3个空位子,这样不断的进入每一左段区域的左端,区域就被每次缩小一半,一定会遇到区域内的空位子小于数据的留的空位子,那么就进入左端,同时,减去该区域的左段空位子,(其实,最后有段只是减去了,他本身该站的一个空位子,前面就留了k个空位)

    没有图。靠大家想象;

    把最核心的代码放这里:(等我把这个搞透,就回来完善)

    if (tree[pos << 1].valu >= valu)ind = query((pos << 1), valu);
       else ind = query((pos << 1 | 1), valu - tree[pos << 1].valu);
       tree[pos].valu = tree[pos << 1].valu + tree[pos << 1 | 1].valu;

    ac代码如下:

    #include<cstdio>
    #define MAXN int(2e5)+5
    struct node
    {
     int l, r, valu;
     int mid(){ return l + ((r - l) >> 1); }
    };
    int x[MAXN], y[MAXN], n, res[MAXN];
    struct Tree
    {
     node tree[MAXN << 2];
     void build(int L, int R, int pos)
     {
      tree[pos].l = L; tree[pos].r = R;
      tree[pos].valu = R - L + 1;
      if (L != R)
      {
       int mid = tree[pos].mid();
       build(L, mid, pos << 1);
       build(mid + 1, R, pos << 1 | 1);
      }
     }
     int query(int pos, int valu)
     {
      int L = tree[pos].l, R=tree[pos].r;
      if (L == R)
      {
       tree[pos].valu = 0;
       return L;
      }
      else
      {
       int ind;
       if (tree[pos << 1].valu >= valu)ind = query((pos << 1), valu);
       else ind = query((pos << 1 | 1), valu - tree[pos << 1].valu);
       tree[pos].valu = tree[pos << 1].valu + tree[pos << 1 | 1].valu;
       return ind;
      }
     }
    };
    Tree tree;
    int main()
    {
     while (scanf("%d", &n) != EOF)
     {
      tree.build(0, n - 1, 1);
      for (int i = 0; i < n; i++)scanf("%d%d", &x[i], &y[i]);
      for (int i = n - 1; i >= 0; --i)
      {
       int pos = tree.query(1, x[i] + 1);
       res[pos] = y[i];
      }
      for (int i = 0; i < n; i++)
      {
       printf("%d%c", res[i], i == n - 1 ? '\n' : ' ');
      }
     }
     return 0;
    }

  • 相关阅读:
    【剑指offer】面试题35:第一个只出现一次的字符
    【剑指offer】面试题34:丑数
    【剑指offer】面试题33:把数组排成最小的数
    【剑指offer】面试题32:从1到n整数中1出现的次数
    【剑指offer】面试题31:连续子数组的最大和
    【剑指offer】面试题30:最小的 k 个数
    【剑指offer】面试题29:数组中出现次数超过一半的数字
    【剑指offer】面试题28:字符串的排列
    【剑指offer】面试题27:二叉搜索树与双向链表
    【剑指offer】面试题26:复杂链表的复制
  • 原文地址:https://www.cnblogs.com/ALINGMAOMAO/p/9404151.html
Copyright © 2011-2022 走看看