首页 > 代码库 > 线段树的基本操作
线段树的基本操作
点更新:
1 #include <fstream> //点更新 2 #include <iostream> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N=10000; 8 int n,m,a[N]; 9 struct node10 {11 int left,right;12 int max_,sum_;13 }tree[4*N];14 15 void build(int id,int l,int r);//建一棵线段树16 int query_sum(int id,int l,int r);//查询区间和17 int query_max(int id,int l,int r);//查询区间最大值18 void update(int id,int pos,int val);//更新位置pos的值增加val19 20 int main()21 {22 //freopen("D:\\input.in","r",stdin);23 //freopen("D:\\output.out","w",stdout);24 int bo,t1,t2;25 scanf("%d%d",&n,&m);26 for(int i=1;i<=n;i++)27 scanf("%d",&a[i]);28 build(1,1,n);29 for(int i=1;i<=m;i++)30 {31 scanf("%d%d%d",&bo,&t1,&t2);32 if(bo)//更新(这里指增加)33 update(1,t1,t2);34 else35 printf("%d\n",query_sum(1,t1,t2));36 }37 return 0;38 }39 void build(int id,int l,int r)40 {41 tree[id].left=l;42 tree[id].right=r;43 if(l==r)44 {45 tree[id].sum_=a[l];46 tree[id].max_=a[l];47 }48 else49 {50 int mid=(l+r)/2;51 build(2*id,l,mid);52 build(2*id+1,mid+1,r);53 tree[id].sum_=tree[2*id].sum_+tree[2*id+1].sum_;54 tree[id].max_=max(tree[2*id].max_,tree[2*id+1].max_);55 }56 }57 int query_sum(int id,int l,int r)58 {59 if(tree[id].left==l&&tree[id].right==r)60 return tree[id].sum_;61 else62 {63 int mid=(tree[id].left+tree[id].right)/2;64 if(r<=mid) return query_sum(2*id,l,r);65 else if(l>mid) return query_sum(2*id+1,l,r);66 else67 return query_sum(2*id,l,mid)+query_sum(2*id+1,mid+1,r);68 }69 }70 int query_max(int id,int l,int r)71 {72 if(tree[id].left==l&&tree[id].right==r)73 return tree[id].max_;74 else75 {76 int mid=(tree[id].left+tree[id].right)/2;77 if(r<=mid) return query_max(2*id,l,r);78 else if(l>mid) return query_max(2*id+1,l,r);79 else80 return max(query_max(2*id,l,mid),query_max(2*id+1,mid+1,r));81 }82 }83 void update(int id,int pos,int val)84 {85 if(tree[id].left==tree[id].right)86 {87 tree[id].sum_+=val;//假如修改而不是增加,就把+=改为=。88 tree[id].max_+=val;89 }90 else91 {92 int mid=(tree[id].left+tree[id].right)/2;93 if(pos<=mid) update(2*id,pos,val);94 else update(2*id+1,pos,val);95 tree[id].sum_=tree[2*id].sum_+tree[2*id+1].sum_;96 tree[id].max_=max(tree[2*id].max_,tree[2*id+1].max_);97 }98 }
区间更新:
1 #include <fstream> 2 #include <iostream> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N=100005; 8 int n,m,a[N]; 9 struct node 10 { 11 int left,right; 12 long long lazy,sum_; 13 }tree[4*N]; 14 15 void build(int id,int l,int r);//建一棵线段树 16 long long query_sum(int id,int l,int r);//查询区间和 17 void update(int id,int p1,int p2,int val);//更新区间[p1,p2]的值增加val 18 19 int main() 20 { 21 //freopen("D:\\input.in","r",stdin); 22 //freopen("D:\\output.out","w",stdout); 23 int bo,t1,t2,t3; 24 scanf("%d%d",&n,&m); 25 for(int i=1;i<=n;i++) 26 scanf("%d",&a[i]); 27 build(1,1,n); 28 for(int i=1;i<=m;i++) 29 { 30 scanf("%d%d%d",&bo,&t1,&t2); 31 if(bo)//更新(这里指增加) 32 { 33 scanf("%d",&t3); 34 update(1,t1,t2,t3); 35 } 36 else 37 printf("%lld\n",query_sum(1,t1,t2)); 38 } 39 return 0; 40 } 41 void build(int id,int l,int r) 42 { 43 tree[id].left=l; 44 tree[id].right=r; 45 tree[id].lazy=0; 46 if(l==r) 47 { 48 tree[id].sum_=a[l]; 49 } 50 else 51 { 52 int mid=(l+r)/2; 53 build(2*id,l,mid); 54 build(2*id+1,mid+1,r); 55 tree[id].sum_=tree[2*id].sum_+tree[2*id+1].sum_; 56 } 57 } 58 long long query_sum(int id,int l,int r) 59 { 60 if(tree[id].left==l&&tree[id].right==r) 61 return tree[id].sum_; 62 else 63 { 64 int mid=(tree[id].left+tree[id].right)/2; 65 if(tree[id].lazy) 66 { 67 update(2*id,tree[id].left,mid,tree[id].lazy); 68 update(2*id+1,mid+1,tree[id].right,tree[id].lazy); 69 tree[id].lazy=0; 70 } 71 if(r<=mid) return query_sum(2*id,l,r); 72 else if(l>mid) return query_sum(2*id+1,l,r); 73 else 74 return query_sum(2*id,l,mid)+query_sum(2*id+1,mid+1,r); 75 } 76 } 77 void update(int id,int p1,int p2,int val) 78 { 79 if(tree[id].left==p1&&tree[id].right==p2) 80 { 81 tree[id].lazy+=val; 82 tree[id].sum_+=val*(p2-p1+1); 83 } 84 else 85 { 86 int mid=(tree[id].left+tree[id].right)/2; 87 if(tree[id].lazy) 88 { 89 update(2*id,tree[id].left,mid,tree[id].lazy); 90 update(2*id+1,mid+1,tree[id].right,tree[id].lazy); 91 tree[id].lazy=0; 92 } 93 if(p2<=mid) 94 update(2*id,p1,p2,val); 95 else if(p1>mid) 96 update(2*id+1,p1,p2,val); 97 else 98 { 99 update(2*id,p1,mid,val);100 update(2*id+1,mid+1,p2,val);101 }102 tree[id].sum_=tree[2*id].sum_+tree[2*id+1].sum_;103 }104 }
需要注意的是:线段树空间应开为原数组长度的4倍。
空间复杂度~O(N*4),每次更新和查询操作的复杂度都是O(logN)。
线段树的基本操作
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。