Prob.4[树状数组]洛谷模板3378/3364总结 Upd:2020.3.2

树状数组:实质上维护一个O(nlogn)的前缀和序列。

模板:

(1)支持单点修改,区间和查询。将区间按lowbit划分,提高效率。

单点更新:对于坐标x加上k:update(x,k)

区间查询:[l,r] Query(r)-Query(l-1);

AC code:

/* Tree Array
*/
#include<cstdio>
using namespace std;
const int N=500020;
int s[600001],n,m;
inline int lowbit(int x)
{
return x & (-x);
}
inline void update(int x,int y)
{
while(x<=N)
{
s[x]+=y;
x+=lowbit(x);
}
}
inline int query(int x)
{
int res=0;
while(x>=1)
{
res+=s[x];
x-=lowbit(x);
}
return res;
}
int main()
{
int a,b,c;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
update(i,a);
}
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
if(a==1)
update(b,c);
else
printf("%d\n",query(c)-query(b-1));
}
return 0;
}

(2)用树状数组维护差分序列:

概念:设已知序列{ai}.{bi}是{ai}的差分序列,当且仅当对于任意i∈N*,都有 bi=ai-a(i-1),这样ai=b1+b2+b3+....bn

如此,加上树状数组的前缀和,我们可以做到区间修改,单点查询的功能。

初始化是有区别的:对于坐标,我们update(x,ai-ai-1)

对于区间修改[l,r](加上k为例) 只需要 update(l,k) update(r+1,-k)即可

单点查询:query(i)=Sum bi=ai

 

#include<cstdio>
using namespace std;
const int N=500002;
int s[N],n,m,a,b,c,d;
inline int lowbit(int x)
{
return x & (-x);
}
inline int update(int x,int y)
{
while(x<=N)
{
s[x]+=y;
x+=lowbit(x);
}
}
inline int query(int x)
{
int res=0;
while(x>=1)
{
res+=s[x];
x-=lowbit(x);
}
return res;
}

int main()
{
int lst=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
update(i,a-lst);
lst=a;
}
for(int i=1;i<=m;i++)
{
scanf("%d",&a);
if(a==1)
{
scanf("%d%d%d",&b,&c,&d);
update(b,d);
update(c+1,-d);
}
else
{
scanf("%d",&b);
printf("%d\n",query(b));
}
}
return 0;
}

posted @ 2020-03-02 22:28  会飞的字符串  阅读(120)  评论(0编辑  收藏  举报