虚二叉树

以前在DD的博客上看到过虚二叉树这个词,很好奇。但是但是水平有限,DD的博客上也只是几句个人的总结而没有具体的讲解,就没有去研究。

今天头脑一热,想起这个词,然后仔细看了一下,发现和我原来在网上看到的一道线段树的实现很相似,代码也相当短。就仔细看了一下。但是这个东西网上资料相当少,不知道是不是有其他名字。在谷歌学术中搜索只有一篇一笔带过的没什么内容的论文,网页搜索也只看到两三个博客且都没有讲解。不过DD的博客上提到2002年李睿的论文讲到了这个,总算有点资料看看了。

我没有看到虚二叉树的明确定义,所以只写一些个人的想法,也不知道对不对。虚二叉树就是省去了二叉树的构造过程的二叉树,或者可以看成一种简化了的特殊的线段树。

很巧的是,看到的论文,我以前写的程序和DD的程序都是POJ 2352/ URAL 1028的。

具体请看

DD的博客 http://cuitianyi.com/blog/%E8%99%9A%E4%BA%8C%E5%8F%89%E6%A0%91/

2002年国家集训队论文 李睿 二分法与统计问题

下面贴几个程序。

我的代码:

#include <stdio.h>
#define MAXN 100000

int tree[MAXN];
int level[MAXN];
int i, j, k, n, m, x, y;


int search(int root, int goal, int left, int right)
{
    tree[root]++;
    if (goal == right)
        return tree[root] - 1;  //找到了,把自己减掉,不用再更新子树了
    int mid = (left + right) / 2;
    if (goal <= mid)
        return search(root * 2, goal, left, mid);
    else
        return tree[root * 2] + search(root * 2 + 1, goal, mid + 1, right);
}


int main()
{
    scanf("%d", &n);
    for (i = 1; i <= n; i++)
    {
        scanf("%d%d", &x ,&y);
        level[search(1, x, 0, MAXN)]++;
    }
    for (i = 0; i < n; i++)
        printf("%d\n", level[i]);
    return 0;
}

 

DD的代码

//URAL 1028

#include <cstdio>

int tree[32001];
int v[15000];

int work(int x){
    int l=0,r=32001,tot=0;
    for(;;){
        int m=(l+r)/2;
        if(x<=m)++tree[m];
        if(x>=m)tot+=tree[m];
        if(x==m)break;
        if(x<m)r=m-1;
        else l=m+1;
    }
    return tot;
}

int main(){
    int N;
    scanf("%d",&N);
    for(int i=0; i<N; ++i ){
        int x,y;
        scanf("%d%d",&x,&y);
        v[work(x)]++;
    }
    for(int i=1; i<=N; ++i )
        printf("%d\n",v[i]);
}

 

论文的伪代码:

function INSERT-AND-GET(y):integer
begin
    l←1,r←n
    ans←0
    while (l<=r) do
        begin
              m=(l+r) div 2
    if  y<=V[m] LESS[m]←LESS[m]+1
    if  y>=V[m] ans←ans+LESS[m]
    if  y =V[m] break
    if  y<V[m] then r ←m –1
       else l←m+1
        end
    return ans
end

posted on 2011-07-29 13:49  oa414  阅读(595)  评论(0编辑  收藏  举报

导航