用各种奇怪的姿势写线段树练习3
线段树练习3是一道codevs上的题目...区间加一个数、区间求和
反正大部分一维数据结构都能过这道题...
区修区查树状数组
#include <iostream> #include <stdio.h> #include <string.h> using namespace std; typedef long long ll; int n,a,m,d,l,r,x; ll a1[200001],a2[200001]; ll qzh(int r) { ll s1=0,s2=0; for(int i=r;i>=1;i-=i&-i) s1+=a1[i], s2+=a2[i]; return (r+1)*s1-s2; } ll sum(int l,int r) { return qzh(r)-qzh(l-1); } void edt(ll a,ll s1) { ll s2=a*s1; for(;a<=n;a+=a&-a) a1[a]+=s1, a2[a]+=s2; } void edt(int l,int r,ll a) {edt(l,a); edt(r+1,-a);} int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a); edt(i,i,a); } scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d",&d); if(d==1) { scanf("%d%d%d",&l,&r,&x); edt(l,r,x); } else { scanf("%d%d",&l,&r); printf("%lld\n",sum(l,r)); } } }
线段树 标记永久化
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <math.h> #include <set> #include <map> using namespace std; int n; typedef long long ll; namespace seg { #define SZ 555555 int M=262144,M2=M+M; ll sum[SZ],tag[SZ]; void edit(int x,int ql,int qr,int v,int l,int r) { if(x>M2||ql>qr||l>r) return; if(ql==l&&qr==r) {tag[x]+=v; return;} sum[x]+=(qr-ql+1)*v; int mid=l+r>>1; edit(x+x,ql,min(qr,mid),v,l,mid); edit(x+x+1,max(mid+1,ql),qr,v,mid+1,r); } ll gsum(int x,int ql,int qr,int l,int r) { if(x>M2||ql>qr) return 0; if(ql==l&&qr==r) return sum[x]+tag[x]*(qr-ql+1); int mid=l+r>>1; return gsum(x+x,ql,min(qr,mid),l,mid)+gsum(x+x+1,max(mid+1,ql),qr,mid+1,r)+tag[x]*(qr-ql+1); } } int q,a,b,c; char buf[3]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { int a=i,b; scanf("%d",&b); seg::edit(1,a,a,b,1,n); } scanf("%d",&q); while(q--) { scanf("%s",buf); if(buf[0]=='2') { scanf("%d%d",&a,&b); printf("%lld\n",seg::gsum(1,a,b,1,n)); } else { scanf("%d%d%d",&a,&b,&c); seg::edit(1,a,b,c,1,n); } } }
线段树 lazytag(不建议学习
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <math.h> #include <set> #include <map> using namespace std; int n; typedef long long ll; namespace seg { #define SZ 555555 int M=262144,M2=M+M,ls[SZ],rs[SZ]; ll sum[SZ],tag[SZ]; void build() { for(int i=M+1;i<=M+M;i++) ls[i]=rs[i]=i-M; for(int i=M-1;i;i--) ls[i]=ls[i+i], rs[i]=rs[i+i+1], sum[i]=sum[i+i]+sum[i+i+1]; } void pd(int x) { if(tag[x]) { sum[x]+=tag[x]*(rs[x]-ls[x]+1); if(x+x<=M2) tag[x+x]+=tag[x], tag[x+x+1]+=tag[x]; tag[x]=0; } } void upd(int x) { pd(x+x); pd(x+x+1); sum[x]=sum[x+x]+sum[x+x+1]; } void edit(int x,int ql,int qr,int v) { if(x>M2||ql>qr) return; pd(x); if(ql==ls[x]&&qr==rs[x]) {tag[x]+=v; return;} int mid=ls[x]+rs[x]>>1; edit(x+x,ql,min(qr,mid),v); edit(x+x+1,max(mid+1,ql),qr,v); upd(x); } ll gsum(int x,int ql,int qr) { if(x>M2||ql>qr) return 0; pd(x); if(ql==ls[x]&&qr==rs[x]) return sum[x]; int mid=ls[x]+rs[x]>>1; ll ans=gsum(x+x,ql,min(qr,mid))+gsum(x+x+1,max(mid+1,ql),qr); upd(x); return ans; } } int q,a,b,c; char buf[3]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lld",&seg::sum[i+seg::M]); scanf("%d",&q); seg::build(); while(q--) { scanf("%s",buf); if(buf[0]=='2') { scanf("%d%d",&a,&b); printf("%lld\n",seg::gsum(1,a,b)); } else { scanf("%d%d%d",&a,&b,&c); seg::edit(1,a,b,c); } } }
splay
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <vector> #include <limits> #include <set> #include <map> using namespace std; #define SZ 233333 typedef long long ll; #define R register int ch[SZ][2],fa[SZ],org[SZ],root,an=0,sz[SZ]; ll sum[SZ],tag[SZ],val[SZ]; void pd(R int x) { if(!x||!tag[x]) return; val[x]+=tag[x]; R int &lc=ch[x][0],&rc=ch[x][1]; if(lc) {tag[lc]+=tag[x]; sum[lc]+=tag[x]*sz[lc];} if(rc) {tag[rc]+=tag[x]; sum[rc]+=tag[x]*sz[rc];} tag[x]=0; } void upd(R int x) { R int &lc=ch[x][0],&rc=ch[x][1]; pd(lc); pd(rc); sz[x]=sz[lc]+sz[rc]+1; sum[x]=val[x]+tag[x]+sum[lc]+sum[rc]; } void rot(R int x) { if(!fa[x]) return; pd(fa[x]); pd(x); R int y=fa[x],c=ch[y][0]==x,&f=fa[y],&s=ch[x][c]; fa[x]=f; if(f) ch[f][ch[f][1]==y]=x; f=x; ch[y][!c]=s; if(s) fa[s]=y; s=y; upd(y); if(y==root) root=x; } void splay(R int x,R int f) { pd(x); R int& y=fa[x]; while(y!=f) { if(fa[y]!=f) { if(ch[fa[y]][0]==y^ch[y][0]==x) rot(x); else rot(y); } rot(x); } upd(x); if(!f) root=x; } void splayp(R int k,R int f) { R int x=root; pd(x); while(sz[ch[x][0]]!=k-1) { if(k<=sz[ch[x][0]]) x=ch[x][0]; else k-=sz[ch[x][0]]+1, x=ch[x][1]; pd(x); } splay(x,f); } int n,q,a,b,c,is[233333]; char buf[3]; void addnode(R int& x,R int f,R int v) {x=++an; fa[x]=f; val[x]=sum[x]=v; sz[x]=1;} void build(R int& x,R int l,R int r,R int f) { if(l>r) {x=0; return;} R int m=(l+r)>>1; addnode(x,f,is[m]); build(ch[x][0],l,m-1,x); build(ch[x][1],m+1,r,x); upd(x); } #define rrl ch[ch[root][1]][0] void build() { addnode(root,0,0); addnode(ch[root][1],root,0); upd(root); build(rrl,1,n,ch[root][1]); upd(ch[root][1]); upd(root); } void getlr(R int l,R int r) {splayp(l,0); splayp(r+2,root);} int main() { scanf("%d",&n); for(R int i=1;i<=n;i++) scanf("%d",is+i); build(); scanf("%d",&q); while(q--) { scanf("%s",buf); if(buf[0]=='2') { scanf("%d%d",&a,&b); getlr(a,b); printf("%lld\n",sum[rrl]); } else { scanf("%d%d%d",&a,&b,&c); getlr(a,b); tag[rrl]+=c; sum[rrl]+=(ll)sz[rrl]*c; } } }
treap
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> #include <math.h> #include <set> #include <map> using namespace std; #define ll long long #define SZ 233333 int ch[SZ][2],sz[SZ],rnd[SZ],an=0,root; ll tag[SZ],val[SZ],sum[SZ]; int Rand() {return rand()<<16+rand();} void addnode(int& ad,int x) { ad=++an; sz[ad]=1; rnd[ad]=Rand(); sum[ad]=val[ad]=x; } void pd(int x) { if(!x||!tag[x]) return; val[x]+=tag[x]; if(ch[x][0]) tag[ch[x][0]]+=tag[x], sum[ch[x][0]]+=tag[x]*sz[ch[x][0]]; if(ch[x][1]) tag[ch[x][1]]+=tag[x], sum[ch[x][1]]+=tag[x]*sz[ch[x][1]]; tag[x]=0; } void upd(int x) { if(!x) return; sz[x]=1+sz[ch[x][0]]+sz[ch[x][1]]; sum[x]=val[x]+sum[ch[x][0]]+sum[ch[x][1]]; } void split(int x,int& a,int& b,int s) { if(sz[x]<=s) a=x, b=0; else if(s==0) a=0, b=x; else { pd(x); if(sz[ch[x][0]]>=s) { b=x; split(ch[x][0],a,ch[x][0],s); upd(x); } else { a=x; split(ch[x][1],ch[x][1],b,s-sz[ch[x][0]]-1); upd(x); } } } void merge(int& ad,int a,int b) { if(a==0) ad=b; else if(b==0) ad=a; else { if(rnd[a]>rnd[b]) { pd(ad=a); merge(ch[a][1],ch[a][1],b); } else { pd(ad=b); merge(ch[b][0],a,ch[b][0]); } upd(ad); } } void edit(int l,int r,ll v) { int a,b,c; split(root,a,b,l-1); split(b,b,c,r-l+1); tag[b]+=v; sum[b]+=v*sz[b]; merge(a,a,b); merge(root,a,c); } ll query(int l,int r) { int a,b,c; split(root,a,b,l-1); split(b,b,c,r-l+1); ll ans=sum[b]; merge(a,a,b); merge(root,a,c); return ans; } int n,ns[SZ]; int ins(int l,int r) { if(l>r) return 0; if(l==r) { int ad; addnode(ad,ns[l]); return ad; } int mid=(l+r)>>1,lc=ins(l,mid),rc=ins(mid+1,r); merge(lc,lc,rc); return lc; } void init() { addnode(root,0); merge(root,ins(1,n),root); } int q,a,b,c; char buf[3]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&ns[i]); init(); scanf("%d",&q); while(q--) { scanf("%s",buf); if(buf[0]=='2') { scanf("%d%d",&a,&b); printf("%lld\n",query(a,b)); } else { scanf("%d%d%d",&a,&b,&c); edit(a,b,c); } } }
下篇文章就写一点数据结构题好了...这篇就当是整理模板好了。