线段树这一类树状结构一般可以用两种形式来实现—数组和指针。 下面学习了一下别人的指针实现的线段树。
和数组实现的一样分为三步:建树,添加值,查询。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int INF_MAX = -999999999; const int INF_MIN = 999999999; int n,q,a,b,t=1,MAX=INF_MAX,MIN=INF_MIN; struct node{ int l,r; int MAX,MIN; node *left, *right; }; node tree[1000000];//可以事先建立结点数组,也可以在建树的过程中动态建立结点,但是这样可以节省递归清内存的时间 void built(node *root,int l,int r){ root->l = l; root->r = r; root->MAX = INF_MAX; root->MIN = INF_MIN; //将结点维护的最值初始化。 if(l!=r){ root->left = &tree[t++]; root->right = &tree[t++]; built(root->left,l,(root->l+root->r)/2); built(root->right,(root->l+root->r)/2+1,r); } } void update(node *root,int i,int v){ if(root->l == i&&root->r == i) { root->MAX = root->MIN = v; return ; //找到该结点就赋值 } root->MIN = min(root->MIN,v); //递归改变母节点的值 root->MAX = max(root->MAX,v); if(i<=(root->l+root->r)/2) update(root->left,i,v); else update(root->right,i,v); } void query(node *root,int l,int r){ if(root->MAX<=MAX&&root->MIN>=MIN) return ; if(l==root->l&&r==root->r) { MIN = min(root->MIN,MIN); MAX = max(root->MAX,MAX); return ; } if(r<=(root->l+root->r)/2) query(root->left,l,r); else if(l>=(root->l+root->r)/2+1) query(root->right,l,r); else { query(root->left,l,(root->l+root->r)/2); query(root->right,(root->l+root->r)/2+1,r); } } int main(){ scanf("%d%d",&n,&q); built(tree,1,n); for(int i=1;i<=n;i++){ scanf("%d",&a); update(tree,i,a); } while(q--){ scanf("%d%d",&a,&b); MAX = INF_MAX; MIN = INF_MIN; query(tree,a,b); printf("%d\n",MAX-MIN); } return 0; }