1. 程式人生 > >線段樹基本操作(單點更新,區間極值,區間求和)

線段樹基本操作(單點更新,區間極值,區間求和)

做了一部分題目,總結一下線段樹的幾個基本操作。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
const int INF=1<<29;
int max_tree[300000];
int min_tree[300000];
int sum_tree[300000]; 
int a[300000];
void build(int node,int begin,int end){//建樹 
	if(begin==end) min_tree[node]=a[begin],max_tree[node]=a[begin],sum_tree[node]=a[begin];
	else{
		build(2*node,begin,(begin+end)/2);
		
		build(2*node+1,(begin+end)/2+1,end);
		
		max_tree[node]=max(max_tree[2*node],max_tree[2*node+1]);
		
		min_tree[node]=min(min_tree[2*node],min_tree[2*node+1]);
		
		sum_tree[node]=sum_tree[2*node]+sum_tree[2*node+1];
	}
}
int findmin(int node,int begin,int end,int z,int y){//找到z--y的最小值 
	int p1=INF,p2=INF;
	if(begin>=z&&end<=y) return min_tree[node];
	int fz=(begin + end) / 2;
	if(z<=fz)
	p1=findmin(2*node,begin,fz, z, y) ;
	if(y>fz)
	p2=findmin(2*node+1,fz+1,end,z,y);
	return min(p1,p2);
}
int findmax(int node,int begin,int end,int z,int y){//找到z--y的最大值 
	int p1=-INF,p2=-INF;
	if(begin>=z&&end<=y) return max_tree[node];
	int fz=(begin + end) / 2;
	if(z<=fz)
	p1=findmax(2*node,begin,fz, z, y) ;
	if(y>fz)
	p2=findmax(2*node+1,fz+1,end,z,y);
	return max(p1,p2);
}
int getsum(int node,int begin,int end,int z,int y){//求z--y的和 
	if(begin>=z&&end<=y) return sum_tree[node];
	int fz=(begin + end) / 2;
	int sum=0;
	if(z<=fz) sum+=getsum(2*node,begin,fz,z,y);
	if(y>fz) sum+=getsum(2*node+1,fz+1,end,z,y);
	return sum;
}
void updata(int node,int begin,int end,int x,int num){//單點更新 
	if(begin==end){
		min_tree[node]=num;
		max_tree[node]=num;
		sum_tree[node]=num;
		return;
	}
	int fz=(begin+end)/2;
	if(x<=fz) updata(node*2,begin,fz,x,num);
	else updata(node*2+1,fz+1,end,x,num);
	min_tree[node]=min(min_tree[2*node],min_tree[2*node+1]);
	max_tree[node]=max(max_tree[2*node],max_tree[2*node+1]);
	sum_tree[node]=sum_tree[2*node]+sum_tree[2*node+1];
}
int main(){
	a[1]=2,a[2]=3,a[3]=8,a[4]=1,a[5]=5,a[6]=7;
	// 2 3 8 1 5 7 
	build(1,1,6);
	cout<<"2 3 8 1 5 7"<<endl; 
	/*
	尋找2--5區間最小值 
	*/ 
	cout<<"2--5區間最小值:"<<findmin(1,1,6,2,5)<<endl;
	/*
	尋找2--5區間最大值 
	*/ 
	cout<<"2--5區間最大值:"<<findmax(1,1,6,2,5)<<endl;
	/*
	 求2--5區間和 
	*/
	cout<<"2--5區間和 :"<<getsum(1,1,6,2,5)<<endl;
	
	
	/*
	 更新a[3]=0,a[4]=10 
	*/
	updata(1,1,6,3,0);
	updata(1,1,6,4,10);
	cout<<"2 3 0 10 5 7"<<endl; 
	//查詢更新後的結果 
	/*
	尋找2--5區間最小值 
	*/ 
	cout<<"2--5區間最小值:"<<findmin(1,1,6,2,5)<<endl;
	/*
	尋找2--5區間最大值 
	*/ 
	cout<<"2--5區間最大值:"<<findmax(1,1,6,2,5)<<endl;
	/*
	 求2--5區間和 
	*/
	cout<<"2--5區間和 :"<<getsum(1,1,6,2,5)<<endl;
	return 0;
}