线段树模板
Posted walfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树模板相关的知识,希望对你有一定的参考价值。
自己写的模板,方便以后查看
求最大值的:
#include<iostream> #include<cstdio> using namespace std; #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 const int maxn=222222; int value[maxn<<2]; void PushUp(int rt) { value[rt]=max(value[rt<<1],value[rt<<1|1]); } void btree(int l,int r,int rt) { //初始为(1,n,1) if(l==r) { scanf("%d",&value[rt]); return ; } int m=(l+r)>>1; btree(ls); btree(rs); PushUp(rt); } void update(int x,int v,int l,int r,int rt) { //初始化为(a,b,1,n,1) if(l==r) { value[rt]=v; return ; } int m=(l+r)>>1; if(x<=m)update(x,v,ls); else update(x,v,rs); PushUp(rt); } int query(int L,int R,int l,int r,int rt) { //初始化为(a,b,1,n,1) if(L<=l&&r<=R)return value[rt]; int m=(l+r)>>1,ans=0; if(L<=m)ans=max(ans,query(L,R,ls)); if(R>m)ans=max(ans,query(L,R,rs)); return ans; } int main() { }
求区间和:
#include<iostream> #include<cstdio> using namespace std; #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 const int maxn=50005; int value[maxn<<2],ans; void PushUp(int rt) { value[rt]=value[rt<<1]+value[rt<<1|1]; } void btree(int l,int r,int rt) { //初始为(1,n,1) if(l==r) { scanf("%d",&value[rt]); return ; } int m=(l+r)>>1; btree(ls); btree(rs); PushUp(rt); } void update(int x,int v,int l,int r,int rt) { //初始化为(a,b,1,n,1) if(l==r) { value[rt]+=v; return ; } int m=(l+r)>>1; if(x<=m)update(x,v,ls); else update(x,v,rs); PushUp(rt); } void query(int L,int R,int l,int r,int rt) { //初始化为(a,b,1,n,1) if(L<=l&&r<=R) { ans+=value[rt]; return ; } if(l==r)return; int m=(l+r)>>1; if(R<=m)query(L,R,ls); else if(L>m)query(L,R,rs); else { query(L,R,ls); query(L,R,rs); } } int main() { return 0; }
区间更新的:
#include<iostream> #include<cstdio> using namespace std; #define ll long long #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 const int maxn=100005; ll value[maxn<<2],add[maxn<<2]; void PushUp(int rt) { value[rt]=value[rt<<1]+value[rt<<1|1]; } void PushDown(int rt,int m)//m是当前节点区间的范围 { //例如1-5 右儿子4-5,左儿子1-3 m=5,m>>1=2刚好是右儿子区间范围,m-(m>>1)=3为左儿子区间范围 if(add[rt])//向下更新子节点 { add[rt<<1]+=add[rt];//更新左儿子的lazy标记 add[rt<<1|1]+=add[rt];//右儿子 value[rt<<1]+=(m-(m>>1))*add[rt];//更新左儿子的权值,应该乘上左儿子区间(r-l+1) value[rt<<1|1]+=(m>>1)*add[rt];//应该乘右儿子区间范围 add[rt]=0; } } void btree(int l,int r,int rt) { //初始化1,n,1 add[rt]=0; if(l==r) { scanf("%lld",&value[rt]); return ; } int m=(l+r)>>1; btree(ls); btree(rs); PushUp(rt); } void update(int L,int R,int c,int l,int r,int rt) { //初始化a,b,c,1,n,1 if(L<=l&&r<=R)//给定区间大于现有区间 { add[rt]+=c;//标记加上 value[rt]+=(ll)c*(r-l+1);//更新当前节点 return ; } PushDown(rt,r-l+1);//向下更新子节点因为下一步要使用子节点 int m=(l+r)>>1; if(L<=m)update(L,R,c,ls); if(R>m)update(L,R,c,rs); PushUp(rt);//向上关系父节点 } ll query(int L,int R,int l,int r,int rt) { //初始化为a,b,1,n,1 if(L<=l&&r<=R)return value[rt]; PushDown(rt,r-l+1); int m=(l+r)>>1; ll ans=0; if(L<=m)ans+=query(L,R,ls); if(R>m)ans+=query(L,R,rs); return ans; } int main() { }
以上是关于线段树模板的主要内容,如果未能解决你的问题,请参考以下文章