线段树

(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\n",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\n",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\n",query(l,r,1));
		}
	}
}

  

posted @ 2017-07-06 12:16  Michael_Zhuang  阅读(97)  评论(0编辑  收藏  举报