zoukankan      html  css  js  c++  java
  • 线段树

    (CodeVS:1082)

    C++指针版

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define ll long long
    using namespace std;
    struct rec{
    	ll l,r,delta,sum;
    	rec *lc,*rc;
    };
    rec *root;
    ll l,r,add,n,m,tmp;
    void update(rec *now,ll l,ll r,ll add)
    {
    	if ((l<=now->l)&&(now->r<=r))
    	{
    		now->delta+=add;
    		return;
    	}
    	if (l<=(now->l+now->r)/2) update(now->lc,l,r,add);
    	if (r>(now->l+now->r)/2) update(now->rc,l,r,add);
    	now->sum=now->lc->sum+(now->lc->r-now->lc->l+1)*now->lc->delta;
    	now->sum+=now->rc->sum+(now->rc->r-now->rc->l+1)*now->rc->delta;
    }
    void build(rec *now,ll l,ll r)
    {
    	now->l=l;now->r=r;
    	if (l==r)
    	{
    		scanf("%lld",&now->sum);
    		now->lc=NULL;now->rc=NULL;
    		return;
    	}
    	now->lc=new rec;
    	now->rc=new rec;
    	build(now->lc,l,(l+r)/2);
    	build(now->rc,(l+r)/2+1,r);
    	now->sum=now->lc->sum+now->rc->sum;
    }
    ll query(rec *now,ll l,ll r)
    {
    	ll ret=0;
    	if ((l<=now->l)&&(now->r<=r))return now->sum+now->delta*(now->r-now->l+1);
    	now->lc->delta+=now->delta;
    	now->rc->delta+=now->delta;
    	now->sum+=now->delta*(now->r-now->l+1);
    	now->delta=0;
    	if (l<=(now->l+now->r)/2)ret=query(now->lc,l,r);
    	if (r>(now->r+now->l)/2)ret+=query(now->rc,l,r);
    	return ret;
    }
    int main()
    {
    	root=new rec;
    	scanf("%lld",&n);
    	build(root,1,n);
    	scanf("%lld",&m);
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%lld",&tmp);
    		if (tmp==1)
    		{
    			scanf("%lld %lld %lld",&l,&r,&add);
    			update(root,l,r,add);			
    		}
    		if (tmp==2)
    		{
    			scanf("%lld %lld",&l,&r);
    			printf("%lld
    ",query(root,l,r));
    		}
    	}
    }
    

    指针+读入优化

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define ll long long
    using namespace std;
    struct rec{
        ll delta,sum,l,r;
        rec *lc,*rc;
    };
    rec *root;
    ll l,r,add,n,m,tmp;
    void read(ll &k)
    {
    	int f=1;char c=getchar();k=0;
    	while (c<'0'||c>'9') c=='-'&&(f=-1),c=getchar();
    	while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
    	k*=f;
    }
    void build(rec *now,ll l,ll r)
    {
        now->l=l;now->r=r;
        if (l==r){read(now->sum);return;}
        now->lc=new rec;
        now->rc=new rec;
        build(now->lc,l,(l+r)>>1);
        build(now->rc,((l+r)>>1)+1,r);
        now->sum=now->lc->sum+now->rc->sum;
    }
    void update(rec *now,ll l,ll r,ll add)
    {
        if ((l<=now->l)&&(now->r<=r)){now->delta+=add;return;}
        if (l<=(now->l+now->r)>>1) update(now->lc,l,r,add);
        if (r>(now->l+now->r)>>1) update(now->rc,l,r,add);
        now->sum=now->lc->sum+(now->lc->r-now->lc->l+1)*now->lc->delta;
        now->sum+=now->rc->sum+(now->rc->r-now->rc->l+1)*now->rc->delta;
    }
    ll query(rec *now,ll l,ll r)
    {
        if ((l<=now->l)&&(now->r<=r))return now->sum+now->delta*(now->r-now->l+1);
        ll ret=0;
        now->lc->delta+=now->delta;
        now->rc->delta+=now->delta;
        now->sum+=now->delta*(now->r-now->l+1);
        now->delta=0;
        if (l<=(now->l+now->r)>>1)ret=query(now->lc,l,r);
        if (r>(now->r+now->l)>>1)ret+=query(now->rc,l,r);
        return ret;
    }
    int main()
    {
        root=new rec;
        read(n);
        build(root,1,n);
        scanf("%lld",&m);
        for (int i=1;i<=m;i++)
        {
            scanf("%lld",&tmp);
            if (tmp==1)
            {
                read(l);read(r);read(add);
                update(root,l,r,add);          
            }
            if (tmp==2)
            {
                read(l);read(r);
                printf("%lld
    ",query(root,l,r));
            }
        }
    }
    

    数组模拟+读入优化

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #define ll long long
    using namespace std;
    ll n,m,l,r,tmp,add;
    const int maxn=200000;
    ll le[maxn*4],ri[maxn*4],delta[maxn*4],sum[maxn*4];
    void read(ll &k)
    {
    	k=0;ll f=1;char c=getchar();
    	while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    	while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
    	k*=f;
    }
    void build(ll l,ll r,ll cur)
    {
    	le[cur]=l;ri[cur]=r;
    	if (l==r){read(sum[cur]);return;}
    	build(l,(l+r)>>1,cur*2);
    	build(((l+r)>>1)+1,r,cur*2+1);
    	sum[cur]=sum[cur*2]+sum[cur*2+1];
    }
    ll query(ll l,ll r,ll cur)
    {
    	if (l<=le[cur]&&ri[cur]<=r)return sum[cur]+delta[cur]*(ri[cur]-le[cur]+1);
    	ll ret=0;
    	delta[cur*2]+=delta[cur];
    	delta[cur*2+1]+=delta[cur];
    	sum[cur]+=delta[cur]*(ri[cur]-le[cur]+1);
    	delta[cur]=0;
    	if (l<=(le[cur]+ri[cur])>>1)ret=query(l,r,cur*2);
    	if (r>(le[cur]+ri[cur])>>1)ret+=query(l,r,cur*2+1);
    	return ret;
    }
    void update(ll l,ll r,ll add,ll cur)
    {
    	if (l<=le[cur]&&r>=ri[cur]){delta[cur]+=add;return;}
    	if (l<=(le[cur]+ri[cur])>>1)update(l,r,add,cur*2);
    	if (r>(le[cur]+ri[cur])>>1)update(l,r,add,cur*2+1);
    	sum[cur]=sum[cur*2]+delta[cur*2]*(ri[cur*2]-le[cur*2]+1);
    	sum[cur]+=sum[cur*2+1]+delta[cur*2+1]*(ri[cur*2+1]-le[cur*2+1]+1);
    }
    int main()
    {
    	read(n);
    	build(1,n,1);
    	read(m);
    	for (int i=0;i<m;i++)
    	{
    		read(tmp);
    		if (tmp==1)
    		{
    			read(l);read(r);read(add);
    			update(l,r,add,1);
    		}
    		if (tmp==2)
    		{
    			read(l);read(r);
    			printf("%lld
    ",query(l,r,1));
    		}
    	}
    }
    

      

  • 相关阅读:
    新的开始——3.3
    第一个周末——3.2
    恋爱知识大增——周五3.1
    相安无事——周四2.28
    好几天没写了。。。——周三2.27
    开学第二天——2.26
    开学第一天——2.25
    华为
    微软 Microsoft
    谷歌 google
  • 原文地址:https://www.cnblogs.com/mczhuang/p/7125625.html
Copyright © 2011-2022 走看看