線段樹基本操作(單點更新,區間極值,區間求和)
阿新 • • 發佈:2018-12-24
做了一部分題目,總結一下線段樹的幾個基本操作。
#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; }