poj3266一道典型线段树

    因为最近想做的一个东西和区间统计有关,心血来潮玩了下线段树。


   #include<iostream>
using namespace std;


#define MAXNUMBER 1<<30


class TreeNode
{
public:
TreeNode();
int leftIndex;
int rightIndex;
int maxHeight;
int minHeight;
TreeNode* leftNode;
TreeNode* rightNode;
};


TreeNode::TreeNode()
{
leftIndex=0;
rightIndex=0;
maxHeight=-1;
minHeight=MAXNUMBER;
leftNode=NULL;
rightNode=NULL;
}


class SegmentTree
{
public:
SegmentTree();
int cowNumber;//node nubmer
TreeNode *treeRoot;
int heightArray[50005];


void InitializeTree();
void FindTreeMinAndMaxValue(TreeNode *tNode);
void QueryTree(TreeNode *tNode,int lIndex,int rIndex,int& min,int& max); 
};


SegmentTree::SegmentTree()
{
treeRoot=NULL;
}


void SegmentTree::InitializeTree()
{
treeRoot=new TreeNode();
treeRoot->leftIndex=0;
treeRoot->rightIndex=this->cowNumber-1;


//Compare the Left Child and Right Child result
FindTreeMinAndMaxValue(treeRoot);


return;
}


void SegmentTree::FindTreeMinAndMaxValue(TreeNode *tNode)
{
//See if the node exists.
if(tNode->leftIndex==tNode->rightIndex)
{
tNode->maxHeight=this->heightArray[tNode->leftIndex];
tNode->minHeight=this->heightArray[tNode->rightIndex];
return;
}


//Find left child min and max value
tNode->leftNode=new TreeNode();
tNode->leftNode->leftIndex=tNode->leftIndex;
tNode->leftNode->rightIndex=(tNode->leftIndex + tNode->rightIndex)/2 ;
if(tNode->leftNode->leftIndex <= tNode->leftNode->rightIndex)//The segmen exists
{
FindTreeMinAndMaxValue(tNode->leftNode);
}
else
{
tNode->leftNode->minHeight=MAXNUMBER;
tNode->leftNode->maxHeight=-1;
}


//Find right child min and max value
tNode->rightNode=new TreeNode();
tNode->rightNode->leftIndex=(tNode->leftIndex+tNode->rightIndex)/2 + 1;
tNode->rightNode->rightIndex=tNode->rightIndex;
if(tNode->rightNode->leftIndex <= tNode->rightNode->rightIndex)//The segmen exists
{
FindTreeMinAndMaxValue(tNode->rightNode);
}
else
{
tNode->rightNode->minHeight=MAXNUMBER;
tNode->rightNode->maxHeight=-1;
}


//merge the resultt
tNode->maxHeight=(tNode->leftNode->maxHeight>tNode->rightNode->maxHeight)?tNode->leftNode->maxHeight:tNode->rightNode->maxHeight;
tNode->minHeight=(tNode->leftNode->minHeight<tNode->rightNode->minHeight)?tNode->leftNode->minHeight:tNode->rightNode->minHeight;


return;
}




void SegmentTree::QueryTree(TreeNode *tNode,int lIndex,int rIndex,int& minHeight,int& maxHeight)
{
if( tNode->leftIndex==lIndex && tNode->rightIndex==rIndex)
{
minHeight=tNode->minHeight;
maxHeight=tNode->maxHeight;
return;
}


//See left child
int leftMinHeight=MAXNUMBER;
int leftMaxHeight=-1;
if(tNode->leftNode->rightIndex >= lIndex)//Interact with left child
{
if(tNode->leftNode->rightIndex < rIndex)//the range interact with left child partly
{
QueryTree(tNode->leftNode,lIndex,tNode->leftNode->rightIndex,leftMinHeight,leftMaxHeight);
}
else//left child conclude the range
{
QueryTree(tNode->leftNode,lIndex,rIndex,leftMinHeight,leftMaxHeight);
}
}


//See right child
    int rightMinHeight=MAXNUMBER;
int rightMaxHeight=-1;
if(tNode->rightNode->leftIndex <= rIndex)//Interact with right child
{
if(tNode->rightNode->leftIndex > lIndex)//the range interacts with the right child partly
{
QueryTree(tNode->rightNode,tNode->rightNode->leftIndex,rIndex,rightMinHeight,rightMaxHeight);
}
else//the right child conclude the range totally
{
QueryTree(tNode->rightNode,lIndex,rIndex,rightMinHeight,rightMaxHeight);
}
}


//Merge the result
minHeight=(leftMinHeight<rightMinHeight)?leftMinHeight:rightMinHeight;
maxHeight=(leftMaxHeight>rightMaxHeight)?leftMaxHeight:rightMaxHeight;


return;
}


int main()
{
SegmentTree sTree;
int answerArray[200002];
int N,Q;
scanf("%d%d",&N,&Q);
sTree.cowNumber=N;
for(int i=0;i<N;i++)
{
scanf("%d",&sTree.heightArray[i]);
}
sTree.InitializeTree();
for(int i=0;i<Q;i++)
{
int minHeight=MAXNUMBER,maxHeight=-1;
int lIndex,rIndex;
scanf("%d%d",&lIndex,&rIndex);
lIndex--;
rIndex--;
sTree.QueryTree(sTree.treeRoot,lIndex,rIndex,minHeight,maxHeight);
answerArray[i]=maxHeight-minHeight;
}


for(int i=0;i<Q;i++)
{
printf("%d\n",answerArray[i]);
}


return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值