zoukankan      html  css  js  c++  java
  • POJ2828 Buy Tickets【线段树,逆序遍历】

    刚开始看到题目,想用memmove偷懒,结果TLE,后来查了查,才发现用memmove也是O(n^2)的复杂度。。。

    #include <stdio.h>
    #include <string.h>
    int seq[222222];
    int main()
    {
        int n,i,j,idx,posi,vali,t;
        while (~scanf("%d",&t))
        {
            memset(seq,0,sizeof(seq));
            for (i=0;i<t;i++)
            {
                scanf("%d%d",&posi,&vali);
                memmove(seq+posi+2,seq+posi+1,sizeof(int)*((i+1)-(posi+1)));
                seq[posi+1]=vali;
            }
            for (i=1;i<=t;i++)
                printf("%d ",seq[i]);
            printf("\b\n");
        }
        return 0;
    }

    在网上找了AC代码,还是没怎么看懂。

    就知道是逆序遍历的,线段树结点存储的是当前区域的空位置数量。

    关键是update函数中的代码看的不是很懂。

    void update(int p,int l,int r,int rt){

      ...  

      if(Tree[rt<<1]>=p){

      update(p,lson);
      }else{
      p-=Tree[rt<<1];
      update(p,rson);

      }
    }

    =======================================

    五一和老婆玩了2天,现在趁着假期结尾把这道题搞明白了。也敢把AC的status贴上了、嘿嘿

    初始状态

    首先是插入3 69

    14结点有4个位置,

    12结点有2个位置,小于3,因此放到14结点右孩子,且14结点空位置减1

    到了14右孩子后,只要找到第3-2=1个位置即可,而34结点的左孩子33含有1个空位置,1>=1,所以放到33位置了。

     

    插入2 33

     

    ★关键是这里如何处理★

    插入2 51

    此时14的左孩子只有1个位置,1<2,所以只能放到14的右孩子34

    34的左孩子有0个位置,所以只能放在34的右孩子44上。

     

    插入1 77

     

     

     

    =======================================

    Problem: 2828   User: qq1203456195
    Memory: 4580K   Time: 1313MS
    Language: C   Result: Accepted
     1 #include <stdio.h>
     2 #define lson l,m,rt<<1
     3 #define rson m+1,r,rt<<1|1
     4 #define maxn 222222
     5 int Tree[maxn<<2];
     6 int Seq[maxn],Pos[maxn],Val[maxn];
     7 int id;
     8 void build(int l,int r,int rt){
     9     int m=((l+r)>>1);
    10     Tree[rt]=r-l+1;
    11     if (l==r)
    12         return;
    13     build(lson);
    14     build(rson);
    15 }
    16 void update(int p,int l,int r,int rt){
    17     int m=(l+r)>>1;
    18     Tree[rt]--;
    19     if (l==r){
    20         id=l;
    21         return;
    22     }
    23     if(Tree[rt<<1]>=p){
    24         update(p,lson);
    25     }else{
    26         p-=Tree[rt<<1];
    27         update(p,rson);
    28     }
    29 }
    30 int main(){
    31     int n,i;
    32     while(scanf("%d",&n)!=EOF)
    33     {
    34         build(1,n,1);
    35         for (i=1;i<=n;i++)
    36             scanf("%d%d",&Pos[i],&Val[i]);
    37         for (i=n;i>=1;i--)
    38         {
    39             update(Pos[i]+1,1,n,1);
    40             Seq[id]=Val[i];
    41         }
    42         printf("%d",Seq[1]);
    43         for (i=2;i<=n;i++)
    44             printf(" %d",Seq[i]);
    45         printf("\n");
    46     }
    47     return 0;
    48 }
    字节跳动内推

    找我内推: 字节跳动各种岗位
    作者: ZH奶酪(张贺)
    邮箱: cheesezh@qq.com
    出处: http://www.cnblogs.com/CheeseZH/
    * 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    for循环中break和continue的区别
    详解vue生命周期及每个阶段适合进行的操作
    ansible部署
    ansible介绍
    jenkins介绍和安装
    查看磁盘型号和内存及raid信息
    shell 概览
    day5 函数和参数
    day4(dict和set)
    day3(if和for)
  • 原文地址:https://www.cnblogs.com/CheeseZH/p/2476134.html
Copyright © 2011-2022 走看看