## poj3266一道典型线段树

2019年04月18日 算法 ⁄ 共 3695字 ⁄ 字号 评论关闭

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

#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 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);