NotOnlySuccess大神的飘逸版线段树

来源:互联网 发布:制作简谱软件下载 编辑:程序博客网 时间:2024/04/29 17:05

吐槽:在模板题,我的丑陋的线段树跑了984ms,而大神的只跑了364ms,看来我的代码还是太丑了QAQ


大神的线段树也没什么大优化,就是不知道为什么超级快,或许是我以前看的线段树代码不好吧。。。
我推荐这个线段树的主要原因就是非常好写,空间也是非常小,思路极其清晰。
好了,废话不多说,直接上代码:

#include<bits/stdc++.h>#define ll long longusing namespace std;const int maxn=100001;ll sum[maxn<<2];ll add[maxn<<2];inline void pushup(int rt){    sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){    if(l==r){        scanf("%lld",&sum[rt]);        return;    }    int mid=(l+r)>>1;    build(l,mid,rt<<1);    build(mid+1,r,rt<<1|1);    pushup(rt);}inline void pushdown(int rt,int len){    if(add[rt]){        add[rt<<1]+=add[rt];        add[rt<<1|1]+=add[rt];        sum[rt<<1]+=add[rt]*(len-(len>>1));        sum[rt<<1|1]+=add[rt]*(len>>1);        add[rt]=0;    }}void update(int L,int R,int c,int l,int r,int rt){    if(L<=l&&r<=R){        add[rt]+=c;        sum[rt]+=c*(r-l+1);        return;    }    pushdown(rt,r-l+1);    int mid=(l+r)>>1;    if(L<=mid)update(L,R,c,l,mid,rt<<1);    if(mid+1<=R)update(L,R,c,mid+1,r,rt<<1|1);    pushup(rt);}ll query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R){        return sum[rt];    }    pushdown(rt,r-l+1);    ll ans=0;    int mid=(l+r)>>1;    if(L<=mid)ans+=query(L,R,l,mid,rt<<1);    if(mid+1<=R)ans+=query(L,R,mid+1,r,rt<<1|1);    return ans;}int main(){    int n,m;    scanf("%d %d",&n,&m);    build(1,n,1);    for(int i=1;i<=m;i++){        int g;        scanf("%d",&g);        if(g&1){            int l,r;            ll c;            scanf("%d %d %lld",&l,&r,&c);            update(l,r,c,1,n,1);        }        else{            int l,r;            scanf("%d %d",&l,&r);            printf("%lld\n",query(l,r,1,n,1));        }    }    return 0;}

以上是区间加+区间和
下面是区间加+区间乘+区间和:(这代码好难调啊)

#include<bits/stdc++.h>#define ll long longusing namespace std;const int maxn=100001;ll p;ll sum[maxn<<2];ll add[maxn<<2];ll mul[maxn<<2];inline void pushup(int rt){    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%p;}inline void mark(int l,int r,int rt,ll a,ll b){    sum[rt]=(sum[rt]*a+(r-l+1)*b)%p;    mul[rt]=(mul[rt]*a)%p;    add[rt]=(add[rt]*a+b)%p;}inline void pushdown(int l,int r,int rt){    if(mul[rt]!=1||add[rt]!=0){        int mid=(l+r)>>1;        mark(l,mid,rt<<1,mul[rt],add[rt]);        mark(mid+1,r,rt<<1|1,mul[rt],add[rt]);        add[rt]=0;        mul[rt]=1;    }}void build(int l,int r,int rt){    mul[rt]=1;    if(l==r){        scanf("%lld",&sum[rt]);        return;    }    int mid=(l+r)>>1;    build(l,mid,rt<<1);    build(mid+1,r,rt<<1|1);    pushup(rt);}void update(int L,int R,int l,int r,int rt,ll a,ll b){    if(L<=l&&r<=R){        mark(l,r,rt,a,b);        return;    }    pushdown(l,r,rt);    int mid=(l+r)>>1;    if(L<=mid)update(L,R,l,mid,rt<<1,a,b);    if(mid+1<=R)update(L,R,mid+1,r,rt<<1|1,a,b);    pushup(rt);}ll query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R){        return sum[rt]%p;    }    pushdown(l,r,rt);    ll ans=0;    int mid=(l+r)>>1;    if(L<=mid)ans+=query(L,R,l,mid,rt<<1);    if(mid+1<=R)ans+=query(L,R,mid+1,r,rt<<1|1);    return ans%p;}int main(){    int n,m;    scanf("%d %d %lld",&n,&m,&p);    build(1,n,1);    for(int i=1;i<=m;i++){        int g;        scanf("%d",&g);        if(g==1){            int l,r;            ll c;            scanf("%d %d %lld",&l,&r,&c);            update(l,r,1,n,1,c,0);        }        else if(g==2){            int l,r;            ll c;            scanf("%d %d %lld",&l,&r,&c);            update(l,r,1,n,1,1,c);        }        else{            int l,r;            scanf("%d %d",&l,&r);            printf("%lld\n",query(l,r,1,n,1));        }    }    return 0;}

end

原创粉丝点击