虚二叉树
以前在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