线段树-模板
Posted waryan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树-模板相关的知识,希望对你有一定的参考价值。
一:线段树介绍
引例:HDU1754
注意到父亲点和左儿子,右儿子的关系,左儿子的序号是父亲的2倍,右儿子的序号是父亲的2倍+1;
建树的过程如下,先建全部的左儿子然后回溯建右儿子和取区间最大值
#include<iostream> #include<algorithm> using namespace std; const int maxn=2e+5; int n,m,a[maxn]; struct tree{ int l,r,v; }trees[maxn<<2];
1.建树
void buildtree(int s,int l,int r) { trees[s].l=l,trees[s].r=r; if(l==r) { trees[s].v=a[l]; return ; } int mid=l+r>>1; buildtree(s<<1,l,mid);//左儿子建立 buildtree(s<<1|1,mid+1,r);//右儿子建立 trees[s].v=max(trees[s<<1].v,trees[s<<1|1].v);//取区间最大值 }
2.单点修改
void update_point(int s,int a,int m) { if(trees[s].l==a&&trees[s].r==a) { trees[s].v=m; return ; } int mid=trees[s].l+trees[s].r>>1; if(a<=mid) update_point(s<<1,a,m);//如果满足这种情况是说明这个点在左儿子的子区间 if(a>mid) update_point(s<<1|1,a,m);//在右儿子的子区间 trees[s].v=max(trees[s<<1].v,trees[s<<1|1].v); }
3.单点修改
4.区间修改
5.区间查询
int ask_interval(int s,int l,int r) { if(trees[s].l==l&&trees[s].r==r) return trees[s].v; int mid=trees[s].l+trees[s].r>>1; if(r<=mid) return ask_interval(s<<1,l,r);//全部在左儿子 if(l>mid) return ask_interval(s<<1|1,l,r);//全部在右儿子 if(l<=mid&&r>mid) return max(ask_interval(s<<1,l,mid),ask_interval(s<<1|1,mid+1,r));//左右儿子区间均有 return 0; }
以上是关于线段树-模板的主要内容,如果未能解决你的问题,请参考以下文章