各類簡單的線段樹模板(來自codevs)
阿新 • • 發佈:2019-02-13
本蒟蒻最近在學線段樹,在學校大佬的推薦下在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~