线段树--数据结构专题学习
2016-04-23 00:18
477 查看
这两周是数据结构专题的学习,,被专题的题目虐得死去活来==
线段树:简单的说就是把【1,n】的区间二分,【1,(1+n)/2】左子树,【(1+n)/2+1,n】右子树
就这样一直分下去,直到都是【x,x】这样的区间。这样就构成了一颗树了^-^
有这样一棵树,我们就可以在节点中储存区间的和啊,区间内的最大值啊,最小值等等。。这就是线段树的附加信息了,也是题目中的重点。。
我们可以用一个数组(长度为k)储存原区间的初始值,然后根据这个建树,所以这个树的节点数最多为4*K;
对于每个节点i,其左子树为i*2,右子树为i*2+1,父母节点为i/2。该区间的sum为左右子树区间和的和,最大最小值同理。。。
线段树的建立,修改,查询都是用递归写的。
所以在对单个数值时,必定会影响到其祖先节点,所以从上往下写。递归后修改节点信息。
线段树的查询也是如此,从上向下查询。
先贴模板
#include <bits/stdc++.h> using namespace std; #define MP make_pair #define PB push_back typedef long long LL; typedef pair<int,int> PII; const double eps=1e-8; const double pi=acos(-1.0); const int K=1e6+7; const int mod=1e9+7; struct node { int max,sum; int left,right; }; struct node tree[4*K]; int a[K]; void build(int id,int l,int r) { tree[id].left=l,tree[id].right=r; if(l==r) tree[id].max=tree[id].sum=a[l]; else { build(2*id,l,(l+r)/2),build(2*id+1,(l+r)/2+1,r); tree[id].max=max(tree[2*id].max,tree[2*id+1].max); tree[id].sum=tree[2*id].sum+tree[2*id+1].sum; } } int queryMax(int id,int l,int r) { if(l==tree[id].left && r==tree[id].right) return tree[id].max; int mid=(tree[id].left+tree[id].right)>>1; if(r<=mid) return queryMax(id<<1,l,r); else if(l>=mid+1) return queryMax((id<<1)+1,l,r); else return max(queryMax(id<<1,l,mid),queryMax((id<<1)+1,mid+1,r)); } int querySum(int id,int l,int r) { if (tree[id].left==l&&tree[id].right==r) return tree[id].sum; int mid=(tree[id].left+tree[id].right)>>1; if (r<=mid) return querySum(id*2,l,r); else if (l>mid) return querySum(id*2+1,l,r); else return querySum(id*2,l,mid)+querySum(id*2+1,mid+1,r); } void update(int id,int pos,int v) { if(tree[id].left == tree[id].right) tree[id].sum=tree[id].max=v; else { int mid=(tree[id].left+tree[id].right)>>1; if (pos<=mid) update(id*2,pos,v); else update(id*2+1,pos,v); tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; tree[id].max=max(tree[id*2].max,tree[id*2+1].max); } } int main(void) { return 0; }
带区间修改的版本:
#include <iostream> #include <algorithm> #include <cstdio> #include <cmath> #include <cstring> #include <queue> #include <stack> #include <map> #include <vector> #include <cstdlib> #include <string> #define PI acos((double)-1) #define E exp(double(1)) using namespace std; #define K 10000 struct node { int maxt,sum,lazy;//sum代表节点信息,按题目更改 int left,right; }; struct node tree[4*K]; int a[K]; void build(int id,int l,int r) { tree[id].left=l;tree[id].right=r;tree[id].lazy=0; if(l==r) { tree[id].maxt=tree[id].sum=a[l]; } else { build(2*id,l,(l+r)/2); build(2*id+1,(l+r)/2+1,r); tree[id].maxt=max(tree[2*id].maxt,tree[2*id+1].maxt); tree[id].sum=tree[2*id].sum+tree[2*id+1].sum; } } void pushdowm(int id) { if(tree[id].lazy) { tree[id*2].lazy=tree[id].lazy; tree[id*2+1].lazy=tree[id].lazy; tree[id*2].sum+=tree[id].lazy; tree[id*2+1].sum+=tree[id].lazy; tree[id].lazy=0; } } int queryMax(int id,int l,int r) { if(l==tree[id].left && r==tree[id].right) return tree[id].maxt; int mid=(tree[id].left+tree[id].right)>>1; int ret=0; pushdowm(id); if(r<=mid) ret=max(ret,queryMax(id<<1,l,r)); else if(l>=mid+1) ret=max(ret,queryMax((id<<1)+1,l,r)); else { int a,b; a=queryMax(id<<1,l,mid); b=queryMax((id<<1)+1,mid+1,r); return max(a,b); } return ret; } int update(int id,int pos,int v) { if(tree[id].left == tree[id].right) { tree[id].sum=tree[id].maxt=v; } else { int mid=(tree[id].left+tree[id].right)>>1; if (pos<=mid) update(id*2,pos,v); else update(id*2+1,pos,v); tree[id].sum=tree[id*2].sum+tree[id*2+1].sum; tree[id].maxt=max(tree[id*2].maxt,tree[id*2+1].maxt); } return 0; } void update_interal(int id,int l,int r,int v) { if(l==tree[id].left && r==tree[id].right) { tree[id].lazy+=v,tree[id].sum+=v;return; } pushdowm(id); int mid=(tree[id].left+tree[id].right)>>1; if(r<=mid) update_interal(id*2,l,r,v); else if(l>mid) update_interal(id*2+1,l,r,v); else { update_interal(id*2,l,mid,v); update_interal(id*2+1,mid+1,r,v); tree[id].sum+=tree[id*2].sum+tree[id*2+1].sum; } } int query(int id,int l,int r) { if (tree[id].left==l&&tree[id].right==r) return tree[id].sum; else { int mid=(tree[id].left+tree[id].right)>>1; pushdowm(id); if (r<=mid) return query(id*2,l,r); else if (l>mid) return query(id*2+1,l,r); else return query(id*2,l,mid)+query(id*2+1,mid+1,r); } } int main(void) { int n,l,r,v; cin>>n; for(int i=1;i<=n;i++) a[i]=i; build(1,1,n); printf("%d\n",query(1,1,10)); cin>>l>>r>>v; update_interal(1,l,r,v); printf("%d\n",query(1,l,r)); return 0; }View Code
相关文章推荐
- 数据结构的二叉链表中序遍历
- 【裸线段树】Uestc-数据结构专题训练【A】
- 【线段树+离散化】Uestc-数据结构专题训练【B】
- 数据结构报告
- Java基础数据结构和算法
- redis中的5种数据结构
- 数据结构与算法(一)概念梳理篇
- 数据结构与算法的学习问题——The Data Structures and Algorithms Learning Problem
- 数据结构--栈(C++实现)
- STL中经常使用数据结构
- 【数据结构】线索化二叉树中序线索化的递归写法和非递归写法
- 一些可运行的C语言数据结构代码
- HDU 3487 Splay
- 数据结构和算法分析
- 数据结构学习-串(2)
- 数据结构与算法分析java——树2(二叉树类型)
- 【数据结构】二叉树(前、中、后)序遍历的递归与非递归算法
- 二叉树的各种基本操作运算多文件组织
- 数据结构与算法分析java——树1
- 选择排序