• 划分树简单介绍


    我感觉划分树的基本思想是二分和归并排序,分为建树和查询两个部分。

    1、建树

      递归建树,以中值为界,将序列划分成左右两部分,直到分到每个点为止。同时,在建树的过程中,记录下每一层进入左区间的数的个数,方便查询时使用。

      注意:保持左右区间中数的相对顺序。

    (1)、中值唯一的情况。将小于等于中值的数放到左区间即可。

    (2)、中值不唯一的情况。为了防止左区间放了过多的和中值相等的数,导致小于中值的数放不进去,需要先统计小于中值的数有多少个,然后用等于中值的数来补全左区间剩余的位置。

        因此需要一个变量来标记一下可放中值数的个数。

    2、查询

      递归查询,判断查询 区间中有多少个进入左区间的数,如果K大于该数,说明所查的数在右区间,否则在左区间。因为该层下一层中左区间的数不全是由所查询区间得出的,还有一部分来自于所查询区间的左侧区间,所以在

    进入下一层查询时,应当避开这些无关的数,右区间亦然。

    具体细节见代码解释:(以 POJ 2104为例)

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<queue>
      7 #include<stack>
      8 #include<deque>
      9 #include<map>
     10 #include<iostream>
     11 using namespace std;
     12 typedef long long  LL;
     13 const double pi=acos(-1.0);
     14 const double e=exp(1);
     15 const int N = 100010;
     16 
     17 #define lson i << 1,l,m
     18 #define rson i << 1 | 1,m + 1,r
     19 
     20 int order[N],tree[20][N];
     21 int lgo[20][N];
     22 int ans=0,n;
     23 
     24 bool cmp(int a,int b)
     25 {
     26     return a<b;
     27 }
     28 
     29 void build(int ceng,int l,int r)
     30 {
     31 
     32     if(l==r)
     33         return ;
     34 
     35     int i,p,j;
     36     int le,ri,flag=0,mid;      //flag存储该进入左区间的中值的个数
     37     mid=(l+r) >> 1;
     38 
     39     flag=mid-l+1;                       //改的地方  左区间所能存的数的个数
     40     for(i=l;i<=r;i++)
     41         if(tree[ceng][i]<order[mid])    //改的地方  左区间中应存有的中值的个数
     42             flag--;
     43 
     44     le=l;
     45     ri=mid+1;
     46     for(i=l;i<=r;i++)
     47     {
     48         if(i==l)
     49             lgo[ceng][i]=0;
     50         else
     51             lgo[ceng][i]=lgo[ceng][i-1];    //记录有多少个数进入左区间
     52 
     53         if(tree[ceng][i]<order[mid]||(tree[ceng][i]==order[mid]&&flag>0))
     54         {
     55             tree[ceng+1][le++]=tree[ceng][i];
     56             lgo[ceng][i]++;
     57             if(tree[ceng][i]==order[mid])
     58                 flag--;
     59         }
     60         else
     61         {
     62             tree[ceng+1][ri++]=tree[ceng][i];
     63         }
     64     }
     65 
     66     build(ceng+1,l,mid);
     67     build(ceng+1,mid+1,r);
     68 }
     69 
     70 void query(int l,int r,int ql,int qr,int ceng,int k)
     71 {
     72 
     73     if(l==r)
     74     {
     75         ans=tree[ceng][l];
     76         return ;
     77     }
     78     int lgol,at_left,at_right,ingol;
     79 
     80     int mid=(l+r) >> 1;
     81 
     82     if(ql==l)
     83         lgol=0;
     84     else
     85         lgol=lgo[ceng][ql-1];       //改  查询区间的左侧区间进入左区间的个数
     86     ingol=lgo[ceng][qr]-lgol;       //改  查询区间进入左区间的个数
     87 
     88     if(k<=ingol)
     89     {
     90         at_left=l+lgol;      //有效的左起始位置
     91         query(l,mid,at_left,at_left+ingol-1,ceng+1,k);
     92     }
     93     else
     94     {
     95         at_left=mid+1+ql-l-lgol;    //有效的左起始位置
     96         query(mid+1,r,at_left,at_left+qr-ql+1-ingol-1,ceng+1,k-ingol);
     97     }
     98 }
     99 
    100 int main()
    101 {
    102     int i,p,j,k;
    103     int a,b,m;
    104     scanf("%d%d",&n,&m);
    105     for(i=1;i<=n;i++)
    106     {
    107         scanf("%d",&tree[0][i]);
    108         order[i]=tree[0][i];
    109     }
    110     sort(order+1,order+1+n,cmp);
    111     build(0,1,n);
    112     for(j=1;j<=m;j++)
    113     {
    114         ans=0;
    115         scanf("%d%d%d",&a,&b,&k);
    116         query(1,n,a,b,0,k);
    117         printf("%d
    ",ans);
    118     }
    119 
    120     return 0;
    121 
    122 }
  • 相关阅读:
    Oracle中有大量的sniped会话
    Error 1130: Host '127.0.0.1' is not allowed to connect to this MySQL server
    汉字转换为拼音以及缩写(javascript)
    高效率随机删除数据(不重复)
    vs2010 舒服背景 优雅字体 配置
    mvc中的ViewData用到webfrom中去
    jquery ajax return值 没有返回 的解决方法
    zShowBox (图片放大展示jquery版 兼容性好)
    动感效果的TAB选项卡 jquery 插件
    loading 加载提示······
  • 原文地址:https://www.cnblogs.com/daybreaking/p/9448926.html
Copyright © 2020-2023  润新知