本蒟蒻最近在学线段树,在学校大佬的推荐下在codevs上发现了三个比较具有代表性的线段树的模板,下面是题面
(当然在这里我只负责提供这三类简单的模板,不负责教授线段树的相关知识,各位大佬,见谅!)
线段树练习代码(单点修改区间查询)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;
struct tree{long long rc,lc,tag,sum;}a[N<<1];
long long A[N],n,m,q,k,x,p,y,ans,t=1;
void pushup(int u){a[u].sum=a[a[u].lc].sum+a[a[u].rc].sum;}
void build(int u,int l,int r){
if(l==r){a[u].sum=A[l];return;}
int mid=(l+r)>>1;
a[u].lc=++t,build(a[u].lc,l,mid);
a[u].rc=++t,build(a[u].rc,mid+1,r);
pushup(u);
}
void update(int u,int l,int r,int x,int w){
if(l==r){a[u].sum+=w;return;}
int mid=(l+r)>>1;
if(x<=mid) update(a[u].lc,l,mid,x,w);
else update(a[u].rc,mid+1,r,x,w);
pushup(u);
}
void query(int u,int l,int r,int ll,int rr){
if(l==ll&&r==rr){ans+=a[u].sum;return;}
int mid=(l+r)>>1;
if(rr<=mid) query(a[u].lc,l,mid,ll,rr);
else if(ll>mid) query(a[u].rc,mid+1,r,ll,rr);
else{query(a[u].lc,l,mid,ll,mid);query(a[u].rc,mid+1,r,mid+1,rr);}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
build(1,1,n);
scanf("%d",&m);
while(m--){
scanf("%d",&q);
if(q==1)scanf("%d%d",&p,&k),update(1,1,n,p,k);
if(q==2)ans=0,scanf("%d%d",&x,&y),query(1,1,n,x,y),printf("%lld\n",ans);
}
return 0;
}
线段树练习2(单点查询区间修改)
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define N 100005
using namespace std;
struct tree{long long rc,lc,sum,tag;}a[N<<1];
long long ans,A[N],t=1,n,m,q,x,y,k,p;
void pushup(int u){a[u].sum=a[a[u].lc].sum+a[a[u].rc].sum;}
void build(int u,int l,int r){
if(l==r) {a[u].sum=A[l];return;};
int mid=(l+r)>>1;
a[u].lc=++t,build(a[u].lc,l,mid);
a[u].rc=++t,build(a[u].rc,mid+1,r);
pushup(u);
}
void pushdown(int u,int l,int r){
int mid=(l+r)>>1;
a[a[u].lc].sum+=a[u].tag*(mid-l+1),a[a[u].lc].tag+=a[u].tag;
a[a[u].rc].sum+=a[u].tag*(r-mid),a[a[u].rc].tag+=a[u].tag;
a[u].tag=0;
}
void update(int u,int l,int r,int ll,int rr,int w){
if(l==ll&&r==rr) {a[u].sum+=w*(r-l+1),a[u].tag+=w;return;}
pushdown(u,l,r);
int mid=(l+r)>>1;
if(rr<=mid) update(a[u].lc,l,mid,ll,rr,w);
else if(ll>mid) update(a[u].rc,mid+1,r,ll,rr,w);
else{update(a[u].lc,l,mid,ll,mid,w);update(a[u].rc,mid+1,r,mid+1,rr,w);}
pushup(u);
}
void query(int u,int l,int r,int x){
if(l==r) {ans+=a[u].sum;return;}
pushdown(u,l,r);
int mid=(l+r)>>1;
if(x<=mid) query(a[u].lc,l,mid,x);
else query(a[u].rc,mid+1,r,x);
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
build(1,1,n);scanf("%lld",&m);
while(m--){
scanf("%lld",&q);
if(q==1) {scanf("%lld%lld%lld",&x,&y,&k),update(1,1,n,x,y,k);}
if(q==2) {scanf("%lld",&p),ans=0,query(1,1,n,p),printf("%lld\n",ans);}
}
return 0;
}
线段树练习3(区间修改区间查询)
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 200005
using namespace std;
struct tree{long long rc,lc,sum,tag;}a[N<<1];
int n,m,q,x,y,k,t=1;
long long A[N],ans;
void pushup(int u){a[u].sum=a[a[u].lc].sum+a[a[u].rc].sum;}
void build(int u,int l,int r){
if(l==r){a[u].sum=A[l];return;}
int mid=(l+r)>>1;
a[u].lc=++t,build(a[u].lc,l,mid);
a[u].rc=++t,build(a[u].rc,mid+1,r);
pushup(u);
}
void pushdown(int u,int l,int r){
int mid=(l+r)>>1;
a[a[u].lc].sum+=(mid-l+1)*a[u].tag;a[a[u].lc].tag+=a[u].tag;
a[a[u].rc].sum+=(r-mid)*a[u].tag;a[a[u].rc].tag+=a[u].tag;
a[u].tag=0;
}
void update(int u,int l,int r,int ll,int rr,int w){
if(l==ll&&r==rr){a[u].sum+=(r-l+1)*w;a[u].tag+=w;return;}
pushdown(u,l,r);
int mid=(l+r)>>1;
if(rr<=mid) update(a[u].lc,l,mid,ll,rr,w);
else if(ll>mid) update(a[u].rc,mid+1,r,ll,rr,w);
else{update(a[u].lc,l,mid,ll,mid,w);update(a[u].rc,mid+1,r,mid+1,rr,w);}
pushup(u);
}
void query(int u,int l,int r,int ll,int rr){
if(l==ll&&r==rr){ans+=a[u].sum;return;}
pushdown(u,l,r);
int mid=(l+r)>>1;
if(rr<=mid) query(a[u].lc,l,mid,ll,rr);
else if(ll>mid) query(a[u].rc,mid+1,r,ll,rr);
else{query(a[u].lc,l,mid,ll,mid);query(a[u].rc,mid+1,r,mid+1,rr);}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&A[i]);
build(1,1,n);
scanf("%d",&m);
while(m--){
scanf("%d",&q);
if(q==1){scanf("%d%d%d",&x,&y,&k);update(1,1,n,x,y,k);}
if(q==2){scanf("%d%d",&x,&y);ans=0;query(1,1,n,x,y);printf("%lld\n",ans);}
}
return 0;
}
在下以不成熟的方式稍微压缩了一下代码量,可能导致代码可读性大大减弱,希望各位理解!!
希望能读到这篇文章的诸位能在今年的比赛中拿到好成绩!
Binggo~