线段树
Posted eric-walker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树相关的知识,希望对你有一定的参考价值。
第一种写法
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define I long long #define FO(i,a,b) for(R I i=a;i<=b;++i) #define fo(i,a,b) for(R I i=a;i<b;++i) #define ll long long #define ls(x) (x<<1) #define rs(x) (ls(x)|1) CT I N =100005; // CT I M = 200005; // const I inf = 2747483647/3; using namespace std; ll sum[N<<2]; ll bt[N<<2]; ll len[N<<2]; I n,m; void down(I son){ bt[ls(son)]+=bt[son]; bt[rs(son)]+=bt[son]; sum[ls(son)]+=bt[son]*len[ls(son)]; sum[rs(son)]+=bt[son]*len[rs(son)]; bt[son]=0; } void insert(I id,I v,I le=1,I re=n,I son=1) { if(le==re){ sum[son]=v; len[son]=1; return ; } I mid=(le+re)>>1; if (id<=mid) { insert(id,v,le,mid,ls(son)); } else { insert(id,v,mid+1,re,rs(son)); } sum[son]=sum[ls(son)]+sum[rs(son)]; len[son]=len[ls(son)]+len[rs(son)]; } void add(I l,I r,I k,I le=1,I re=n,I son=1){ if(l<=le&&re<=r){ sum[son]+=k*len[son]; bt[son]+=k; return ; } I mid=(le+re)>>1; down(son); if(l<=mid){add(l,r,k,le,mid,ls(son));} if(r>mid){add(l,r,k,mid+1,re,rs(son));} sum[son]=sum[ls(son)]+sum[rs(son)]; } ll getsum(I l,I r,I le=1,I re=n,I son=1){ if(l<=le&&re<=r){ return sum[son]; } down(son); I mid=(le+re)>>1; ll ans=0; if(l<=mid) ans+=getsum(l,r,le,mid,ls(son)); if(r>mid) ans+=getsum(l,r,mid+1,re,rs(son)); return ans; } int main(){ scanf("%lld%lld",&n,&m); FO(i,1,n){ I x; scanf("%lld",&x); insert(i,x); } FO(i,1,m){ I x; scanf("%lld",&x); if (x==1) { I l,r,k; scanf("%lld%lld%lld",&l,&r,&k); add(l,r,k); } else { I l,r; scanf("%lld%lld",&l,&r); cout<<getsum(l,r)<<endl; } } return 0; }
第二种写法
#include<iostream> #include<cstdio> using namespace std; inline int ls(int x){return x<<1;} inline int rs(int x){return x<<1|1;} struct FFF{ int l,r; int sum; int tag; int mid(){return l+r>>1;} int len(){return r-l+1;} }t[100000<<2]; int read(); int n; void pushup(int o){ t[o].sum=t[ls(o)].sum+t[rs(o)].sum; } void pushdown(int o){ int & v=t[o].tag; t[ls(o)].tag+=v; t[rs(o)].tag+=v; t[ls(o)].sum+=v*t[ls(o)].len(); t[rs(o)].sum+=v*t[rs(o)].len(); v=0; } void build(int l=1,int r=n,int o=1){ t[o].l=l;t[o].r=r; if(l==r){ t[o].sum=read(); return; } int mid=t[o].mid; build(l,mid,ls(o)); build(mid+1,r,rs(o)); } void add(int l,int r,int k,int o=1){ if(l<=t[o].l&&t[o].r<=r){ t[o].sum+=k*t[o].len(); t[o].tag+=k; return ; } int mid=t[o].mid(); pushdown(o); if(l<=mid){add(l,r,k,ls(o));} if(r>mid){add(l,r,k,rs(o));} pushup(o); } int getsum(int l,int r,int o=1){ if(l<=t[o].l&&t[o].r<=r){ return t[o].sum; } pushdown(o); int mid=t[o].mid(); int ans=0; if(l<=mid) ans+=getsum(l,r,ls(o)); if(r>mid) ans+=getsum(l,r,rs(o)); return ans; } int main(){ return 0; }
以上是关于线段树的主要内容,如果未能解决你的问题,请参考以下文章