zoukankan      html  css  js  c++  java
  • 划分树学习笔记

    参考链接:http://blog.renren.com/blog/367737224/728617495

             http://www.cppblog.com/MatoNo1/archive/2011/06/27/149604.aspx

    在你看这篇文章之前,我认为你已经学习过线段树了。。。

    (1)划分树是干什么的?给出一个长度为n的数列a:a[1],a[2]……a[n]。划分树是求一个给定区间[L,R]中的第K小的数。

           比如n=10:0 5 2 7 5 4 3 8 7 7,L=2,R=6,K=2,则应输出4。

    (2)划分树的建立:划分树采用递归建树,设当前建立数组a的[L,R]区间,在建立的过程中记录一个数组tot[dep][i],表示在第dep层,在[L,i]区间的数中,分到当前层(就是第dep层)的左子树的数的个数。建立时,首先将[L,R]区间的数升序排序,找到中位数mid=(L+R)>>1,则左子树的数字个数为Lnum=mid-L+1,右子树的数字个数为Rnum=R-mid。扫描排序后的区间,小于中位数的分到左子树,大于中位数的分到右子树,等于中位数的看左子树放满没(即放够Lnum个没),没有满放到左子树,否则放到右子树。接着递归建立子树,L=R时返回。

    (3)查找:在大区间[a,b]中查找小区间[L,R]中的第K大数,设当前层为dep,x=tot[dep][L-1],y=tot[dep][R]-tt[dep][L-1],xx=L-a-x,yy=R-L+1-y,则x,y表示区间[a,L-1]和[L,R]中分到左子树的数的个数,xx,yy表示区间[a,L-1]和[L,R]中分到右子树的数的个数。若y>=K,则在左子树中递归查找,L=a+x,R=a+x+y-1,K不变;否则在右子树中递归查找L=mid+1+xx,R=mid+1+xx+yy-1,K=K-y。L=R时返回。

     1  const int MAX=100005;
     2  
     3  struct Node
     4  {
     5      int L,R;
     6  };
     7  
     8  struct HuaFen_tree
     9  {
    10      Node a[MAX<<2];
    11      int s[MAX],t[35][MAX],tot[35][MAX];
    12  
    13      void input(int n)
    14      {
    15          int i;
    16          for(i=1;i<=n;i++)
    17          {
    18              scanf("%d",&s[i]);
    19              t[1][i]=s[i];
    20          }
    21          sort(s+1,s+n+1);
    22      }
    23      void build(int dep,int u,int L,int R)
    24      {
    25          a[u].L=L;
    26          a[u].R=R;
    27          if(L==R) return;
    28          int i,mid=(L+R)>>1;
    29          int sameNum=mid-L+1;
    30          for(i=L;i<=R;i++) if(t[dep][i]<s[mid]) sameNum--;
    31          int LL=L,LR=mid,RL=mid+1,RR=R;
    32          int Lnum=0,Rnum=0;
    33          for(i=L;i<=R;i++)
    34          {
    35              if(i==L) tot[dep][i]=0;
    36              else tot[dep][i]=tot[dep][i-1];
    37              if(t[dep][i]<s[mid])
    38              {
    39                  tot[dep][i]++;
    40                  t[dep+1][LL+Lnum]=t[dep][i];
    41                  Lnum++;
    42              }
    43              else if(t[dep][i]>s[mid])
    44              {
    45                  t[dep+1][RL+Rnum]=t[dep][i];
    46                  Rnum++;
    47              }
    48              else
    49              {
    50                  if(sameNum>0)
    51                  {
    52                      sameNum--;
    53                      tot[dep][i]++;
    54                      t[dep+1][LL+Lnum]=t[dep][i];
    55                      Lnum++;
    56                  }
    57                  else
    58                  {
    59                      t[dep+1][RL+Rnum]=t[dep][i];
    60                      Rnum++;
    61                  }
    62              }
    63          }
    64          build(dep+1,u<<1,LL,LR);
    65          build(dep+1,u<<1|1,RL,RR);
    66      }
    67  
    68      //在区间[a[u].L,a[u].R]这个区间中查找[L,R]中的第K大值
    69      int query(int dep,int u,int L,int R,int K)
    70      {
    71          if(L==R) return t[dep][L];
    72          int x,y,xx,yy,_L,_R,mid=(a[u].L+a[u].R)>>1;
    73          if(L==a[u].L) x=0;
    74          else x=tot[dep][L-1]; //x为[a[u].L,L-1]中分到左边的
    75          y=tot[dep][R]-x;      //y为[L,R]中分到左边的
    76          if(y>=K)
    77          {
    78              _L=a[u].L+x;
    79              _R=a[u].L+x+y-1;
    80              return query(dep+1,u<<1,_L,_R,K);
    81          }
    82          else
    83          {
    84              xx=L-a[u].L-x;  //xx是[a[u].L,L-1]中分到右边的
    85              yy=R-L+1-y;     //yy是[L,R]中分到右边的
    86              _L=mid+1+xx;
    87              _R=mid+1+xx+yy-1;
    88              return query(dep+1,u<<1|1,_L,_R,K-y);
    89          }
    90      }
    91  };
    92   
  • 相关阅读:
    关于在VS2008和VS2010中禁用及卸载Visual Assist X的方法研究——转载
    泛型
    100个常用的Linux命令——转载
    BZOJ1501 (NOI2005 智慧珠游戏)
    Vijos1615 旅行
    Vijos1617 超级教主
    POJ2689 HDU2824 筛法、欧拉函数
    (SPOJ687,后缀数组)
    POJ1743 (Musical Theme,后缀数组)
    POJ2774 Long Long Message
  • 原文地址:https://www.cnblogs.com/jianglangcaijin/p/6036331.html
Copyright © 2011-2022 走看看