线段树的实现求解格子操作

线段树的原理具体参考百度百科,下面的代码实现的叶子节点不是标准的元线段,而是点!根据具体的需要可以自己设计叶子节点的含义。节点里面包含了常用的max,min,sum域信息。

例如: 在[0,7]区间上建立一棵满二叉树:

                                               【0,7】
                               /                                            \
                     【0,3】                                           【4,7】
                  /               \                                    /                \
       【0,1】             【2,3】                       【4,5】               【6,7】
         /      \                 /      \                     /      \                   /      \
【0,0】 【1,1】       【2,2】 【3,3】         【4,4】 【5,5】      【6,6】 【7,7】



问题描述

有n个格子,从左到右放成一排,编号为1-n。

共有m次操作,有3种操作类型:

1.修改一个格子的权值,

2.求连续一段格子权值和,

3.求连续一段格子的最大值。

对于每个2、3操作输出你所求出的结果。

输入格式

第一行2个整数n,m。

接下来一行n个整数表示n个格子的初始权值。

接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。

输出格式

有若干行,行数等于p=2或3的操作总数。

每行1个整数,对应了每个p=2或3操作的结果。

样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3
数据规模与约定

对于20%的数据n <= 100,m <= 200。

对于50%的数据n <= 5000,m <= 5000。

对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。



LineTree.h 头文件

#ifndef LINETREE_H
#define LINETREE_H


#include <assert.h>
#include <vector>
#include <stdio.h>
using namespace std;
class TreeNode
{
 public:
   TreeNode *leftChild;
   TreeNode *rightChild;
 
   int leftBoundry;
   int rightBoundry;
 
   int value;
   bool needUpdate;
 
   int max;
   int min;
   int sum;
 public:
	 
	TreeNode()
	{
		leftChild=rightChild=NULL;
		value=max=min=sum=0;
		needUpdate=true;
	
	}
	TreeNode(int l,int r,int v)
	{
		leftBoundry=l;
		rightBoundry=r;
		value=v;
		max=min=sum=0;
		needUpdate=true;
	
	}
	
	TreeNode(int l,int r,int v,TreeNode *ll,TreeNode * rl)
	{
		leftChild=ll;
		rightChild=rl;
		leftBoundry=l;
		rightBoundry=r;
		value=v;   
		max=min=sum=0;
		needUpdate=true;
	
	}
};


class LineTree
{
public:
	TreeNode *root;
	int leftLimit,rightLimit;
	LineTree()
	{
		root=NULL;
		leftLimit=rightLimit=0;
	
	}
	
	void Build(int l,int r,vector<int> &values,TreeNode * &root);
	void SetLimits(int lLimit,int rLimit);

	bool SetNodeValue(TreeNode *& root,int pos,int value);
	void GetNeedData(TreeNode * &root,int &sum,int &min,int &max);

	bool GetZoneData(TreeNode *&root,int l,int r,int &sum,int &min,int &max);

};

#endif


LineTree.cpp 实现文件
#include "LineTree.h"

void LineTree::Build(int l,int r,vector<int> &values,TreeNode * &root)
{
	assert(values.size()==r-l+1);
	if(r==l)
	{
		root=new TreeNode(l,r,values[0]);
		return;
	}
	else
	{
	 
      root=new TreeNode(l,r,0);
	  int mid=(l+r)/2;
	  vector<int> lValues,rValues;
	  lValues.resize(mid-l+1,0);
	  rValues.resize(r-mid,0);

	  int i;
	  for( i=0;i<lValues.size();i++)
		  lValues[i]=values[i];
	  for(int j=0;i<values.size();i++,j++)
		  rValues[j]=values[i];
	  
	  Build(l,mid,lValues,root->leftChild);
	  Build(mid+1,r,rValues,root->rightChild);
	  
	}
	

}

void LineTree::SetLimits(int lLimit,int rLimit)
{
	rightLimit=rLimit;
	leftLimit=lLimit;
}
bool LineTree::SetNodeValue(TreeNode *& root,int pos,int value)
{
	if( this->root==NULL )
		return false;
	if(root->leftBoundry==pos &&root->rightBoundry==pos)
	{
		root->value=value;
		root->needUpdate=true;
		return true;
	}
	int mid=(root->leftBoundry+root->rightBoundry)/2;
	root->needUpdate=true;
	if(pos<=mid && pos>=root->leftBoundry)
	{
		return SetNodeValue(root->leftChild,pos,value);
	}
	else if(pos>=mid+1 && pos<=root->rightBoundry)
	{
		return SetNodeValue(root->rightChild,pos,value);
	}
	else
		return false;
}
void LineTree::GetNeedData(TreeNode * &root,int &sum,int &min,int &max)
{   
	if(root==NULL)return;
    if(root->needUpdate==false)
	{
		sum=root->sum;
		min=root->min;
		max=root->max;
		return;
	}
	else
	{
		root->needUpdate=false;
		if(root->leftBoundry==root->rightBoundry)
		{
			sum=root->sum=root->value;
			max=root->max=root->value;
			min=root->min=root->value;
			return;
		}

		int lSum,lMin,lMax;
		int rSum,rMin,rMax;

		GetNeedData(root->leftChild,lSum,lMin,lMax);
		GetNeedData(root->rightChild,rSum,rMin,rMax);

		sum=root->sum=lSum+rSum;
		min=root->min=lMin<rMin?lMin:rMin;
		max=root->max=lMax>rMax?lMax:rMax;
	}
}
bool LineTree::GetZoneData(TreeNode *&root,int l,int r,int &sum,int &min,int &max)
{
	if(root==NULL)
		return false;
	if(l<root->leftBoundry || r>root->rightBoundry)
		return false;
	if(l==root->leftBoundry && r==root->rightBoundry)
	{ 
		 GetNeedData(root,sum,min,max); 	
		 return true;
	}
	else
	{
	 int mid=(root->leftBoundry+root->rightBoundry)/2;
	 if(r<=mid)
	 {
		return GetZoneData(root->leftChild,l,r,sum,min,max);
	 }
	 else if(l>=mid+1)
	 {
		return GetZoneData(root->rightChild,l,r,sum,min,max);
	 }
	 else
	 {
		int lSum,lMin,lMax;  
		int rSum,rMin,rMax;

		bool b1=GetZoneData(root->leftChild,l,mid,lSum,lMin,lMax);
		bool b2=GetZoneData(root->rightChild,mid+1,r,rSum,rMin,rMax);

		sum=lSum+rSum;
		min=lMin<rMin?lMin:rMin;
		max=lMax>rMax?lMax:rMax;
		return b1&&b2;
	 }	 
	}
}


main.cpp 测试文件
#include "LineTree.h"
using namespace std;

int main()
{
	LineTree example;
	int sum,min,max;
	vector <int> values;
	values.resize(5,0);
	for(int i=0;i<values.size();i++)
		values[i]=i+1;
	example.SetLimits(1,5);
	example.Build(1,5,values,example.root);

 	example.SetNodeValue(example.root,4,10);
	example.GetNeedData(example.root,sum,min,max);

	example.SetNodeValue(example.root,2,15);

	example.GetNeedData(example.root,sum,min,max);

	example.SetNodeValue(example.root,1,-3);

	example.GetNeedData(example.root,sum,min,max);

	example.GetZoneData(example.root,4,4,sum,min,max);



}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值