恩就是这样,我来画个图说明存储的数据吧:线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。
线段树至少支持下列操作:
Insert(t,x):将包含在区间 int 的元素 x 插入到树t中;
Delete(t,x):从线段树 t 中删除元素 x;
Search(t,x):返回一个指向树 t 中元素 x 的指针。
#include <iostream> using namespace std; const int maxN =1000007; const int oo = 0x0fffffff; struct Tnode { int l, r; int max; int lc, rc; }; Tnode f[maxN]; int fp=0; int root; int getPoint(int l, int r, int max) { fp++; f[fp].l = l; f[fp].r = r; f[fp].max = max; return fp; }//存数据 int create(int l, int r) { int now = getPoint(l,r,-oo); if (l<r) { f[now].lc =create(l, (l+r)/2); f[now].rc= create((l+r)/2+1, r); } return now; }//建立一棵线段树 void update(int root , int p, int x) { int l = f[root].l; int r = f[root].r; if ( p<l || r<p ) return ; if (l==r) { f[root].max=x; return; }//找到要修改的点,进行修改 update(f[root].lc, p, x);//往左边找要修改的值 update(f[root].rc, p, x);//往右边找要修改的值 f[root].max = max ( f [ f[root].lc ].max, f [ f[root].rc ].max );//修改当前节点最大值 }//修改第p个数据 int query(int root,int l,int r) { if (l==f[root].l && r==f[root].r) return f[root].max; int mid = (f[root].l+f[root].r) / 2; int ans = -oo; if (l <= mid) ans = max(ans,query(f[root].lc,l,min(mid,r)));//查找左边最大值 if (r >= mid+1) ans = max(ans,query(f[root].rc,max(mid+1,l),r));//查找右边最大值 return ans; }//查询一段的最大值 int n; int q; int main() { cin >> n; root = create(1,n); cin >> q; char oper; int l,r,p,v; for (int i=0;i<q;++i){ cin >> oper; if (oper == 'F')//找一段的最大值 { cin >> l >> r; cout << query(root,l,r) << endl; } else if (oper == 'I')//修改一个值 { cin >> p >> v; update(root,p,v); } } return 0; }