“树状数组进阶”顾名思义,就是在树状数组性质行的进阶啦
BIT-2
时间限制:1秒 内存限制:128M
题目描述
给定数组
a
1
a_1
a1,
a
2
a_2
a2,
a
3
a_3
a3…
a
n
a_n
an,进行q此操作,操作有两种:
1 l r k
:将
a
i
a_i
ai~
a
k
a_k
ak每个数都加上 k;
2 k
:输出
a
k
a_k
ak.
输入描述
第一行:输入两个数 n,q,表示给定数组的长度和操作数
第二行:输入n个数,表示长度为n的给定数组
接下来q行:每行输入表示如题的某一种操作
输出描述
对于每个2操作,输出对应结果
输入样例
3 2
1 2 3
1 1 3 1
2 2
输出样例
3
数据描述
1<=n,q<=
1
0
6
10^6
106
|
a
i
a^i
ai|=
1
0
6
10^6
106
对于输入:保证
1≤≤≤∣∣≤1061≤l≤r≤,∣k∣≤106
由于树状数组只支持单点修改,所以我们需要把区间转化为单点操作,所以这里我们引入差分思想组,这样就可以把一个区间操作转变成单点操作,而单点查询就是求前面的一个减去后面的一个的前缀和,所以我们只需要用树状数组来维护一个差分数组即可。
代码如下:
#include <iostream>
using namespace std;
const int INF=0x3f3f3f3f;//定一个最小值
const int N=1e6+5;
long long b[N],c[N],n,q,ans=0,x;
long long lowbit(int x)
{
return x&-x;
}
long long query(int x)
{
long long anss=0;
for(int i=x;i;i-=lowbit(i))
{
anss+=b[i];
}
return 0;
}
void update(int l,int r,int x)
{
for(int i=1;i<=n;i+=lowbit(i))
{
b[i]+=x;
}
for(int i=r+1;i<=n;i+=lowbit(i))
{
b[i]-=x;
}
}
int main()
{
cin>>n>>q;
for(int i=1;i<=n;i++)
{
scanf("%d",&x);
update(i,i,x);
}
int k,l,r;
while(q--)
{
int op;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&l,&r,&x);
update(l,r,x);
}
else{
scanf("%d",&x);
printf("%lld\n",query(x));
}
}
}
Hello?