線段樹是一種二叉搜索樹,與區間樹相似,它將一個區間劃分成一些單元區間,每個單元區間對應線段樹中的一個葉結點
#include<stdio.h>
#include<algorithm>
using namespace std;
struct Node
{
int Sum; // 和
int Max; //最大值
int Min; //最小值
int l; //左區間
int r; //右區間
}Tree[4000];
void PushUp(int o)
{
Tree[o].Sum = Tree[o*2].Sum + Tree[o*2+1].Sum ;
Tree[o].Max = max( Tree[o*2].Max , Tree[o*2+1].Max );
Tree[o].Min = min( Tree[o*2].Min , Tree[o*2+1].Min );
}
void Build(int o,int l,int r) //建樹
{
Tree[o].l=l; Tree[o].r=r;
if(l==r) //到達底層,遞歸終止。
{
int t;
scanf("%d",&t);
Tree[o].Sum = Tree[o].Max = Tree[o].Min = t;
return ;
}
int mid=(l+r)/2;
Build(o*2,l,mid);
Build(o*2+1,mid+1,r);
PushUp(o);
}
void UpDate(int o,int l,int r,int x,int y) //把節點x的數據更新爲y
{
if(l==r)
{
Tree[o].Max = Tree[o].Min = Tree[o].Sum = y;
return ;
}
int mid=(l+r)/2;
if(x > mid) //更新的節點在右邊;
UpDate(o*2+1,mid+1,r,x,y);
else // 節點在左邊;
UpDate(o*2,l,mid,x,y);
PushUp(o); //更新當前節點數據
}
int FindSum(int o,int l,int r,int x,int y) //查找x到y的和
{
if(l==x && r==y)
{
return Tree[o].Sum;
}
int mid = (l+r) / 2;
if(y<=mid)
return FindSum(o*2,l,mid,x,y);
else if(x>mid)
return FindSum(o*2+1,mid+1,r,x,y);
else
return FindSum(o*2,l,mid,x,mid)+FindSum(o*2+1,mid+1,r,mid+1,y);
}
int FindMax(int o,int l,int r,int x,int y)
{
if(l==x && r==y)
{
return Tree[o].Max ;
}
int mid = (l+r) / 2;
if(y<=mid)
return FindMax(o*2,l,mid,x,y);
else if(x>mid)
return FindMax(o*2+1,mid+1,r,x,y);
else
return max( FindMax(o*2,l,mid,x,mid), FindMax(o*2+1,mid+1,r,mid+1,y) );
}
int FindMin(int o,int l,int r,int x,int y)
{
if(l==x && r==y)
{
return Tree[o].Min ;
}
int mid = (l+r) / 2;
if(y<=mid)
return FindMin(o*2,l,mid,x,y);
else if(x>mid)
return FindMin(o*2+1,mid+1,r,x,y);
else
return min( FindMin(o*2,l,mid,x,mid), FindMin(o*2+1,mid+1,r,mid+1,y) );
}
int main()
{
int n;
scanf("%d",&n);
Build(1,1,n);
//UpDate(1,1,n,2,7);
printf("%d\n",FindSum(1,1,n,2,4));
printf("Max(2~4)%d\n",FindMax(1,1,n,2,4));
printf("Min(2~4)%d\n",FindMin(1,1,n,2,4));
return 0;
}
/*
4
1 3 2 6
*/