树状数组+线段树

本文详细介绍了数据结构中的线段树和树状数组,包括它们的基础操作如单点修改、区间查询,以及更复杂的区间修改、区间查询等。线段树与树状数组是高效解决动态区间问题的重要工具,适用于处理动态更新和查询的场景。文章通过实例展示了如何实现这些操作,并提供了清晰的代码模板。
摘要由CSDN通过智能技术生成

线段树,树状树组的基本操作(模板)

树状数组:

1.单点修改,区间查询
2.区间修改,单点查询
3.区间修改,区间查询

零.基础:

#define lowbit(x) x&(-x)

一.单点修改,区间查询

1.T[ ]内的元素

  for(int i=1;i<=n;i++) //直接将a[ ]存入T[ ]年内进行维护
	{
		cin>>a[i];
		add(i,a[i]);
   }

2.(存储T [ ])/(修改)

void add(int i,int x)
{
	while(i<=n)
	{
		T[i]+=k;
		i+=lowbit(i);
	}
}

3.询问

int getsum(int i)
{
	int res=0;
	while(i)
    {
    	res+=T[i];
		i-=lowbit(i); 
	}
   return res;
}

二.区间修改,单点查询

1.T[ ]内的元素

for(int i=1;i<=n;i++)
{
  cin>>a[i];
  add(i,a[i]-a[i-1);//这里用其差分来存进
}

2.区间修改

int l,r,k; //需要修改的区间[l,r],以及修改的大小k
cin>>l>>r>>k;
add(l,k);
add(r+1,-k);

3.询问:如上。

三.区间修改,区间查询

1.t1[ ],t2[ ]的元素(需要用2个数组来维护),如上(t2用其差分存储)
2.存储/修改:

void add(int i,int k)
{
int x=i;
  while(i<=n)
  {
    t1[i]+=k;
    t2[i]+=(x-1)*k;
    i+=lowbit(i)
  }
}

3.查询

int getsum(int i)
{
int res=0;
int x=i;
while(i)
{
res+=s1[i]*x-s2[i];
i-=lowbit(i);
}
return res;
}

//其中 
int l,r;
cin>>l>>r;
int ans;
ans=getsum(r)-getsum(l-1);

线段树

1.建树
2.单点修改
3.区间查询,区间修改

0.懒惰标记:

void push_down(int i,int l,int r)
{
if(lz[i])
{
int mid=(l+r)>>1;
  lz[i*2]+=lz[i];
  lz[i*2+1]+=lz[i];
  T[i*2]+=(mid-l+1)*lz[i];
  T[i*2+1]+=(r-mid)*lz[i];
  lz[i]=0;
}
}

1.建树:

void built(int i,int l,int r)
{
  if(l==r)
  {cin>>T[i];
  return;
  }
  int mid=(l+r)>>1;
  built(i*2,l,mid);
  built(i*2+1,mid+1,r);
  T[i]=T[i*2]+T[i*2+1];
}

2.单点修改

void updata(int pos,int i,int k,int l,int r)
{
   if(l==r)
   {T[i]+=k;
   return;
   }
   int mid=(l+r)>>1;
   if(pos<=mid)
     updata(pos,i*2,k,l,mid);
   else
     updata(pos,i*2+1,mid+1,r);
}

3.区间修改,区间查询:

void updata_arrange(int i,int k,int l,int r,int L,int R)//区间修改
{
   if(l>=L && r<=R)
   {
     T[i]+=k*(R-L+1);
     lz[i]+=k;
     return;
   }
   push_down(i,l,r);
   int mid=(l+r)>>1;
   if(mid>=L)
     updata_arange(i*2,k,l,mid,L,R);
    if(mid<R)
      updata_arange(i*2+1,k,mid+1,r,L,R);
     T[i]=T[i*2]+T[i*2+1];
}

int q_arrange(int i,int l,int r,int L,int R)
{
int sum=0;
   if(l>=L && r<=R)
   {
   sum+=T[i];
   return sum;
   }
   push_down(i,l,r);
   int mid=(l+r)>>1;
   if(mid>=L)
   {
   sum+=q_arrange(i*2,l,mid,L,R);
   }
   if(mid<R)
     sum+=q_arrange(i*2+1,mid+1,r,L,R);
    return sum;
}

Con:简而精,欲知其所以然者,另觅高就

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dai _ tu

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

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

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

打赏作者

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

抵扣说明:

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

余额充值