解题思路:
用一个数组存放线段树。根节点下标为0。假设线段树上某节点下标为i, 则:
左子节点下标为 i *2+1
右子节点下标为 i*2+2
由二叉树的定义可知叶子节点为n个时至多需要4n-1个节点
1 #include <cstdio> 2 #include <iostream> 3 const int inf=0x3f3f3f3f; 4 int maxn,minn; 5 struct node 6 { 7 int l,r,mid; 8 int maxn,minn; 9 }; 10 node t[800000]; 11 void init(int root,int l,int r) 12 { 13 t[root].l=l; 14 t[root].r=r; 15 t[root].mid=(l+r)/2; 16 t[root].minn=inf; 17 t[root].maxn=-inf; 18 if(l!=r) 19 { 20 init(2*root+1,l,(l+r)/2); 21 init(2*root+2,(l+r)/2+1,r); 22 } 23 } 24 void insert(int root,int x,int num) 25 { 26 if(t[root].l==t[root].r) 27 { 28 t[root].minn=t[root].maxn=num; 29 return; 30 } 31 t[root].minn=std::min(t[root].minn,num); 32 t[root].maxn=std::max(t[root].maxn,num); 33 if(x<=t[root].mid) 34 insert(2*root+1,x,num); 35 else 36 insert(2*root+2,x,num); 37 } 38 void query(int root,int l,int r) 39 { 40 if(t[root].minn>=minn&&t[root].maxn<=maxn) 41 return; 42 if(t[root].l==l&&t[root].r==r) 43 { 44 minn=std::min(t[root].minn,minn); 45 maxn=std::max(t[root].maxn,maxn); 46 return; 47 } 48 if(r<=t[root].mid) 49 query(2*root+1,l,r); 50 else if(l>t[root].mid) 51 query(2*root+2,l,r); 52 else 53 { 54 query(2*root+1,l,t[root].mid); 55 query(2*root+2,t[root].mid+1,r); 56 } 57 } 58 int main() 59 { 60 int n,q,h; 61 scanf("%d%d",&n,&q); 62 init(0,1,n); 63 for(int i=1;i<=n;i++) 64 { 65 scanf("%d",&h); 66 insert(0,i,h); 67 } 68 int l,r; 69 for(int i=1;i<=q;i++) 70 { 71 scanf("%d%d",&l,&r); 72 maxn=-inf; 73 minn=inf; 74 query(0,l,r); 75 printf("%d ",maxn-minn); 76 } 77 return 0; 78 }