1.维护区间最大最小值模板(以维护最小值为例)
#include<iostream> #include<stdio.h> #define LEN 11 #define MAX 1<<30 using namespace std; int arr[LEN]={1,3,7,6,8,5,3,2,7,2,9}; int st[LEN*3]; //segment tree int n; void init(int len){ n=1; while(n<len) n*=2; //不断乘以2,知道>=len for(int i=0;i<n;i++) st[i]=MAX; } void update(int p,int v){ //我们有n(len的二次幂扩增)个叶子作为线段元素 p+=n-1; //地址重定向,变为叶子节点所在地址 st[p]=v; while(p>0){ p=(p-1)/2; //向上跳转到父节点 st[p]=min(st[p*2+1],st[p*2+2]); //更新父节点 } } // 查询[a,b)的最小值,当前函数的查询是[l,r) 。当前根节点为p int query(int a,int b,int p,int l,int r){//外部调用: query(a,b,0,0,n) //如果[a,b)与[l,r)不相交 if(a>=r || b<=l) return MAX; //如果[a,b)包裹住了[l,r) if(a<=l && b>=r) return st[p]; //其他情况,二分进行查询 int v1=query(a,b,p*2+1,l,(l+r)/2); int v2=query(a,b,p*2+2,(l+r)/2,r); return min(v1,v2); } int main(){ init(LEN); int i,a,b; for(i=0;i<LEN;i++) update(i,arr[i]); while(1){ scanf("%d%d",&a,&b); printf("%d ",query(a,b,0,0,n)); } return 0; }
2.维护区间和的模板
数据结构:
struct node { int left,right; int num; }tree[2000010];
建树:
void build(int left,int right,int index) //build(1,n,1); { he++; tree[index].left=left; tree[index].right=right; if(left==right) return ; int mid=(right+left)/2; build(left,mid,index*2); build(mid+1,right,index*2+1); }
单点修改:
void my_plus(int index,int dis,int k) //将索引为p的元素增加k { // my_plus(1,p,k) tree[index].num+=k; if(tree[index].left==tree[index].right) //没有叶子节点 return ; if(dis<=tree[index*2].right) my_plus(index*2,dis,k); if(dis>=tree[index*2+1].left) my_plus(index*2+1,dis,k); }
单点查询:
int search(int index,int dis) //调用方法:查找索引为p的元素:search(1,p) { if(tree[index].left==tree[index].right && tree[index].left==dis) return tree[index].num; if(dis<=tree[index*2].right) search(index*2,dis); if(dis>=tree[index*2+1].left) search(index*2+1,dis); }
区间修改:
void pls(int index,int l,int r,int k) { if(tree[index].left>=l && tree[index].right<=r) { tree[index].num+=k; return ; } if(tree[index*2].right>=l) pls(index*2,l,r,k); if(tree[index*2+1].left<=r) pls(index*2+1,l,r,k); }
区间查询:
void search(int index,int l,int r) { //cout<<index<<" "; if(tree[index].left>=l && tree[index].right<=r) { ans+=tree[index].num; return ; } if(tree[index*2].right>=l) search(index*2,l,r); if(tree[index*2+1].left<=r) search(index*2+1,l,r); }
3.模板编写练习: