zoukankan      html  css  js  c++  java
  • 递归线段树模板

    加了点注释,方便以后看

    #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
    ",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)<<'
    ';
        }
        return 0;
    }
    
  • 相关阅读:
    Java的静态块与实例块(转)
    Programming Ability Test学习 1031. Hello World for U (20)
    Programming Ability Test学习 1011. World Cup Betting (20)
    Programming Ability Test学习 1027. Colors in Mars (20)
    Programming Ability Test学习 1064. Complete Binary Search Tree (30)
    Programming Ability Test学习 1008. Elevator (20)
    【maven详解-生命周期】Maven的生命周期和插件
    【maven详解-插件】maven插件学习之源码插件Source Xref
    $(document).ready(){}、$(fucntion(){})、(function(){})(jQuery)onload()的区别
    你还没真的努力过,就轻易输给了懒惰
  • 原文地址:https://www.cnblogs.com/syhien/p/7705057.html
Copyright © 2011-2022 走看看