树状数组 线段树模板

树状数组

用来在频繁对某一个位置修改的情况下求前缀和
树状数组维护的区间下标从1开始

int tr[N],lv[N];
int lowbit(int x)
{
	return x&-x;
}
void add(int x, int v)
{
    for (int i = x; i <N; i += lowbit(i)) tr[i] += v;
}

int sum(int x)
{
	int res=0;
	for(int i=x;i>0;i-=lowbit(i))res+=tr[i];
	return res;
}

初始化:
    for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
    for (int i = 1; i <= n; i ++ ) add(i, a[i]);
lowbit
lowbit(x)=x&-x=2^k;
//(k是x末尾连续0的个数,例如4末尾两个0,lowbit(4)=2^2=4)

//也可以理解为x的最后一位1的权重

线段树

用来在频繁对某一个位置修改的情况下求前缀和
要求根节点u从1开始

	static class node
	{
		int l,r,sum;
	}
	static node tr[]=new node [N*4];
	static void pushup(int u)
	{
		tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
	}
	static void build(int u,int l,int r)
	{
		tr[u]=new node();
		tr[u].l=l;
		tr[u].r=r;
		if(l==r)tr[u].sum=w[l];
		else 
		{
			int mid=l+r>>1;
			build(u<<1,l,mid);
			build(u<<1|1,mid+1,r);
			pushup(u);
		}
	}
	static int query(int u,int l,int r)
	{
		if(l<=tr[u].l&&r>=tr[u].r)return tr[u].sum;
		else 
		{
			int mid=tr[u].l+tr[u].r>>1;
			int sum=0;
			if(l<=mid)sum+=query(u<<1,l,r);
			if(r>mid)sum+=query(u<<1|1,l,r);
			return sum;
		}
	}
	
	static void modify(int u,int x,int v)
	{
		if(tr[u].l==tr[u].r)tr[u].sum+=v;
		else {
			int mid=tr[u].l+tr[u].r>>1;
			if(x<=mid)modify(u<<1,x,v);
			else modify(u<<1|1,x,v);
			pushup(u);
		}
	}
区别

树状数组一般只能用来求前缀和,而线段树除了求部分区间内的前缀和还可以求一些其他的,比如区间内最大值
下面是示例:

static int INF_MIN=-2147483648;
    static class node
    {
        int l,r,maxv;
    }
    static node tr[]=new node [4*N];
    static void pushup(int u)
    {
        tr[u].maxv=Math.max(tr[u<<1].maxv, tr[u<<1|1].maxv);
    }
    static void build(int u, int l,int r)
    {
    	tr[u]=new node();
    	tr[u].l=l;
    	tr[u].r=r;
    	if(l==r)tr[u].maxv=w[r];
    	else 
    	{
    		int mid=l+r>>1;
        	build(u<<1,l,mid);
        	build(u<<1|1,mid+1,r);
        	pushup(u);
    	}
    }
    static int query(int u,int l,int r)
    {
    	if(tr[u].l>=l&&tr[u].r<=r)return tr[u].maxv;
    	int mid=tr[u].l+tr[u].r>>1;
    	int res=-INF_MIN;
    	if(l<=mid)res=query(u<<1,l,r);
    	if(r>mid)res=Math.max(res,query(u<<1|1,l,r));
    	return res;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wow_awsl_qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值