用各种奇怪的姿势写线段树练习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
",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
",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
",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
",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
",query(a,b));
        }
        else
        {
            scanf("%d%d%d",&a,&b,&c);
            edit(a,b,c);
        }
    }
}

下篇文章就写一点数据结构题好了...这篇就当是整理模板好了。

原文地址:https://www.cnblogs.com/zzqsblog/p/5692627.html