递归线段树模板

加了点注释,方便以后看

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long a[100001],tree[100000<<2],add[100000<<2],n,m;//<<2即*4
//tree[]为线段树数组
//add[]为lazy tags
//a[]为数组
inline void inl(long long &p,char c=getchar(),bool f=0)//支持负数的读入优化
{
	while((c<'0' or c>'9') and c!='-')
		c=getchar();
	p=0;
	if(c=='-')
		f=1,c=getchar();
	while(c>='0' and c<='9')
		p=p*10+c-'0',c=getchar();
	if(f)
		p=-p;
}
inline void pushup(int rt)//更新rt节点
{
	tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void pushdown(int rt,int ln,int rn)
{
	//ln:left tree的数字数量
	if(add[rt])
	{
		add[rt<<1]+=add[rt];
		add[rt<<1|1]+=add[rt];
		tree[rt<<1]+=add[rt]*ln;
		tree[rt<<1|1]+=add[rt]*rn;
		add[rt]=0;
	}
}
void build(int l,int r,int rt)//递归建树
{
	if(l==r)//到达叶子节点
	{
		tree[rt]=a[l];
		return ;
	}
	int m=(l+r)>>1;
	build(l,m,rt<<1);//left tree
	build(m+1,r,rt<<1|1);//right tree
	pushup(rt);//更新rt的信息
}
void change(int L,int R,int x,int l,int r,int rt)//L R为修改的区间,l r表示当前区间
{
	if(L<=l and R>=r)//当前区间被完全包含了
	{
		tree[rt]+=x*(r-l+1);//更新rt的值
		add[rt]+=x;//记笔记 记笔记
		return ;
	}
	int m=(l+r)>>1;
	pushdown(rt,m-l+1,r-m);//向下推tags
	if(L<=m)//判断当前节点的left,right tree和操作区间有没有交集
		change(L,R,x,l,m,rt<<1);
	if(R>m)
		change(L,R,x,m+1,r,rt<<1|1);
	pushup(rt);//更新rt
}
long long query(int L,int R,int l,int r,int rt)
{
	if(L<=l and R>=r)
		return tree[rt];
	int m=(l+r)>>1;
	pushdown(rt,m-l+1,r-m);
	long long ans=0;
	if(L<=m)
		ans+=query(L,R,l,m,rt<<1);
	if(R>m)
		ans+=query(L,R,m+1,r,rt<<1|1);
	return ans;
}
int main()
{
	//freopen("sth.in","r",stdin);
	inl(n);inl(m);
	for(int i=1;i<=n;i++)
		inl(a[i]);
	build(1,n,1);
	long long t,x,y,k;
	while(m--)
	{
		inl(t);inl(x);inl(y);
		if(t==1)
		{
			inl(k);
			change(x,y,k,1,n,1);
		}
		else
			printf("%lld\n",query(x,y,1,n,1));
	}
	return 0;
}

新操作,区间乘
区间乘需要把add也乘,每次下放都先乘后加

#include<iostream>
using namespace std;
#define LL long long
#define pushup(rt) tree[rt]=tree[rt<<1]+tree[rt<<1|1]

LL n,m,mo;
LL a[1000001];
LL tree[1000001],mul[1000001],add[1000001];

void build(int rt,int l,int r)
{
    mul[rt]=1;
    if(l==r)
    {
        tree[rt]=a[l];
        return ;
    }
    int m=(l+r)>>1;
    build(rt<<1,l,m);
    build(rt<<1|1,m+1,r);
    pushup(rt);
}

void pushdown(int rt,int ln,int rn)
{
	if(mul[rt]!=1)
		(mul[rt<<1]*=mul[rt])%=mo,
		(mul[rt<<1|1]*=mul[rt])%=mo,
		(add[rt<<1]*=mul[rt])%=mo,
		(add[rt<<1|1]*=mul[rt])%=mo,
		(tree[rt<<1]*=mul[rt])%=mo,
		(tree[rt<<1|1]*=mul[rt])%=mo,
		mul[rt]=1;
	if(add[rt])
		(add[rt<<1]+=add[rt])%=mo,
		(add[rt<<1|1]+=add[rt])%=mo,
		(tree[rt<<1]+=add[rt]*ln)%=mo,
		(tree[rt<<1|1]+=add[rt]*rn)%=mo,
		add[rt]=0;
}

void change_mul(int rt,int L,int R,int l,int r,int x)
{
    if(L<=l and R>=r)
    {
        (mul[rt]*=x)%=mo,
        (tree[rt]*=x)%=mo,
		(add[rt]*=x)%=mo;;
        return ;
    }
    int m=(l+r)>>1;
	pushdown(rt,m-l+1,r-m);
    if(L<=m)
        change_mul(rt<<1,L,R,l,m,x);
    if(R>m)
        change_mul(rt<<1|1,L,R,m+1,r,x);
    pushup(rt);
}

void change_add(int rt,int L,int R,int l,int r,int x)
{
    if(L<=l and R>=r)
    {
        (add[rt]+=x)%=mo;
        (tree[rt]+=x*(r-l+1))%=mo;
        return ;
    }
    int m=(l+r)>>1;
	pushdown(rt,m-l+1,r-m);
    if(L<=m)
        change_add(rt<<1,L,R,l,m,x);
    if(R>m)
        change_add(rt<<1|1,L,R,m+1,r,x);
    pushup(rt);
}

LL getans(int rt,int L,int R,int l,int r)
{
    if(L<=l and R>=r)
        return tree[rt];
    int m=(l+r)>>1;
    pushdown(rt,m-l+1,r-m);
    pushup(rt);
    LL ans1=0,ans2=0;
    if(L<=m)
        ans1=getans(rt<<1,L,R,l,m);
    if(R>m)
        ans2=getans(rt<<1|1,L,R,m+1,r);
    return (ans1+ans2)%mo;
}

int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m>>mo;
    for(int i=1;i<=n;i++)
        cin>>a[i];
    build(1,1,n);
    
    while(m--)
    {
        int caozuo,l,r;
        cin>>caozuo>>l>>r;
        if(caozuo==1)
        {
            int cheng;
            cin>>cheng;
            change_mul(1,l,r,1,n,cheng);
        }
        else if(caozuo==2)
        {
            int pls;
            cin>>pls;
            change_add(1,l,r,1,n,pls);
        }
        else
            cout<<getans(1,l,r,1,n)<<'\n';
    }
    return 0;
}
posted @ 2017-11-09 21:23  syhien  阅读(192)  评论(0编辑  收藏  举报