基础线段树(建树,查询,单点更新)
线段树就是讲一连串的数字转换成树的形式,有利于对数据进行操作,效率较高
下面是建树操作
1 void build(int l,int r,int i)//左节点 l 右节点 r 当前节点 i 2 { 3 if(l==r)//找到节点 存入数据 4 { 5 scanf("%d",&sum[i]); 6 return ; 7 } 8 int m=(l+r)>>1,ls=i<<1,rs=ls|1;// m 为中点 ls 为左儿子 rs 为右节点 9 build(l,m,ls);//建立左子树 10 build(m+1,r,rs);//建立右子树 11 pushup(i); //更新父节点 自定义函数 12 }
下面是线段树查询操作代码
查询操作根据不同的题目有不同的写法(其实基本上都是相同的,只是有一点不同)
int query(int L,int R,int l,int r,int i)// 查询的区间(L,R) 起始区间(l,r) 当前节点 i { if(L<=l&&r<=R)//所要查找的区间包含所有节点 { return sum[i]; } int m=(l+r)>>1,ls=i<<1,rs=ls|1; int ans=0; if(L<=m) ans+=query(L,R,l,m,ls);//求和
/*sum[i]=max(sum[i<<1],sum[i<<1|1];
求最值*/
if(R>m)
ans+=query(L,R,m+1,r,rs);
/*sum[i]=max(sum[i<<1],sum[i<<1|1];
求最值*/ return ans; }
接下来是单点更新
在线段树中找到特定的一个节点, 对其数值进行更新
void update(int k,int v,int l,int r,int i)//需要更新的节点 k 更新后的数值 v 起始区间(l,r) 当前节点 i { if(l==r)//找到指定的节点 { sum[i]+=v;//对数值进行更新 此句依题意写 return ; } int m=(l+r)>>1,ls=i<<1,rs=ls|1; //下面是递归操作,细细琢磨,有点二分的味道 if(k<=m) update(k,v,l,m,ls); else update(k,v,m+1,r,rs); pushup(i);//更新父节点 }
https://blog.csdn.net/yitongjun/article/details/53193724
上面这个链接的博客关于线段的 写的很全面
ps:第一次写,不喜勿喷
浙公网安备 33010602011771号