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;
    }
    
  • 相关阅读:
    LocalSessionFactoryBean有几个属性查找hibernate映射文件
    关于Spring中配置LocalSessionFactoryBean来生成SessionFactory
    【Spring源码分析】配置文件读取流程
    Java序列化接口的作用总结1
    Java序列化接口的作用总结
    hibernate抓取策略
    170531、FormData 对象的使用
    170530、java 迭代hashmap常用的三种方法
    170529、springMVC 的工作原理和机制
    170526、spring 执行定时任务
  • 原文地址:https://www.cnblogs.com/syhien/p/7705057.html
Copyright © 2011-2022 走看看