您的位置:首页 > 其它

pku 暑假培训1 线段树和树状数组

2012-07-17 11:29 337 查看
今天是郭炜老师讲的线段树和树状数组,我还记得假期时雄哥讲的这个方面,讲的更加深入一些,举了几道例题让我们了解线段树的性质和应用(主要是开辟的结构体内应当存些什么内容),线段树的离散化,以及树状数组的证明问题。讲的例题貌似和雄哥讲的一样。

下面附上自己的代码和讲解:

poj 3264 line up

#include<stdio.h>
const int MAX=-9999999;
const int MIN= 9999999;
struct node{
int left ,right;      // 线段树上的区间长度
int nmax,nmin;         //每个区间上的最大值和最小值
struct node *pleft,*pright;         //左孩子指针,有孩子指针 要注意到,完全二叉树的叶子结点数为n,则总结点的个数为2n-1;
} tree[500000];
int count=0;
int pmax,pmin;
int min(int a,int b){                         //比较大小函数
if(a<b)return a;
else return b;
}
int max(int a,int b){
if(a>b)return a;
else return b;
}

void buildtree(struct node *proot,int l,int r)             //建树的函数
{
proot->left=l;                                //确定区间的范围
proot->right=r;
proot->nmax=MAX;                                  //初始化最大值,最小值
proot->nmin=MIN;
if(l!=r){
count++;

proot->pleft=tree+count;                        // 用数组的首地址来表示树
buildtree(proot->pleft,l,(r+l)/2);
count++;

proot->pright=tree+count;
buildtree(proot->pright,(r+l)/2+1,r);                  //递归的建树
}
}

void insert(struct node *proot,int num,int i)                //插入数据,并对数据进行更新
{
if(proot->left==i&&proot->right==i){                      // 遇到叶子结点的更新
proot->nmax=num;
proot->nmin=num;
return ;
}
proot->nmax=max(proot->nmax,num);
proot->nmin=min(proot->nmin,num);                   // 遇到包含节点的区间的更新

if(i<=(proot->left+proot->right)/2){
insert(proot->pleft,num,i);
}
if(i>=(proot->left+proot->right)/2+1){

insert(proot->pright,num,i);
}
}

void query(struct node *proot,int b,int e)
{
if(pmax>=proot->nmax && pmin<=proot->nmin)return;       // 一种剪枝的方法
if(proot->left==b&&proot->right==e)
{
pmax=max(proot->nmax,pmax);                            //寻找最大值,最小值
pmin=min(proot->nmin,pmin);

return;
}

if(e<=(proot->left+proot->right)/2)query(proot->pleft,b,e);          //继续进行遍历
else {if(b>=(proot->left+proot->right)/2+1)query(proot->pright,b,e);
else {
query(proot->pleft,b,(proot->left+proot->right)/2);
query(proot->pright,(proot->left+proot->right)/2+1,e);
}
}

}

int main()
{
int n,q,i,num,s,e;
scanf("%d %d",&n,&q);
buildtree(tree,1,n);
for(i=1;i<=n;i++)
{
scanf("%d",&num);
insert(tree,num,i);
}
for(i=1;i<=q;i++)
{
scanf("%d %d",&s,&e);
pmax=MAX;                             // 全局变量记录最大值和最小值
pmin=MIN;
query(tree,s,e);
printf("%d\n",pmax-pmin);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: