单点修改 区间查询
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL long long
#define N 500006
#define lowbit(x) x&-x
using namespace std;
inline LL wread(){
char c(getchar ());LL wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
return wans*=flag;
}
int n,m;
LL a[N];
//单点修改
void add (int pos,LL x){
while (pos<=n){
a[pos]+=x;
pos+=lowbit(pos);
}
}
//查询 [1,pos] 之和
LL askd(int pos){
LL ans(0);
while (pos>0){
ans+=a[pos];
pos-=lowbit(pos);
}
return ans;
}
int main (){
scanf ("%d%d",&n,&m);
for (int i(1);i<=n;++i){
LL x(wread());
//加入原数组
add(i,x);
}
while (m--){
int opr;
scanf ("%d",&opr);
if (opr==1){
int pos;
scanf ("%d",&pos);LL x(wread());
//修改单个值
add(pos,x);
}
else {
int x,y;
scanf ("%d%d",&x,&y);
//相减
printf("%lld\n",askd(y)-askd(x-1));
}
}
return 0;
}
区间修改 单点查询
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define lowbit(x) x&-x
#define LL long long
#define N 500007
using namespace std;
inline int wread(){
char c(getchar ());int wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
return wans*=flag;
}
inline LL ll_wread(){
char c(getchar ());LL wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
return wans*=flag;
}
int n,m;
LL a[N],cha[N];
//原数组 查分数组
//所有操作是基于查分数组来做的,不是原数组哦
void add (int pos,LL x){
while (pos<=n){
cha[pos]+=x;
pos+=lowbit(pos);
}
}
LL askd(int pos){
LL ans(0);
while (pos>0){
ans+=cha[pos];
pos-=lowbit(pos);
}
return ans;
}
int main (){
n=wread();m=wread();
for (int i(1);i<=n;++i)
a[i]=ll_wread();
for (int i(1);i<=n;++i)
add(i,a[i]-a[i-1]);//把查分后的值加入数组
while (m--){
int opr(wread());
if (opr==1){
int x(wread()),y(wread());LL k(ll_wread());
add(x,k);//同样利用查分思想
add(y+1,-k);
}
else {
int pos(wread());
printf("%lld\n",askd(pos));
}
}
return 0;
}
区间修改 区间查询
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#define LL long long
#define lowbit(x) x&-x
using namespace std;
inline int wread(){
char c(getchar ());int wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
return wans*=flag;
}
inline LL ll_wread(){
char c(getchar ());LL wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar ();}
return wans*=flag;
}
LL c[200005][2];
int n,q;
void add(int pos,LL x,int f)
{
while(pos<=n)
{
c[pos][f]+=x;
pos+=lowbit(pos);
}
}
LL query(int pos,int f)
{
LL res=0;
while(pos>0)
{
res+=c[pos][f];
pos-=lowbit(pos);
}
return res;
}
LL ask(int pos)
{
LL res=(pos+1)*query(pos,0)-query(pos,1);
return res;
}
int main()
{
n=wread();q=wread();
LL a(0);
for(int i=1;i<=n;i++)
{
LL b(ll_wread());
add(i,b-a,0);
add(i,(b-a)*i,1);
a=b;
}
while (q--)
{
int opt(wread());
if(opt==1)
{
int a(wread()),b(wread());LL x(ll_wread());
add(a,x,0);
add(b+1,-x,0);
add(a,x*a,1);
add(b+1,-x*(b+1),1);
}
else if(opt==2)
{
int a(wread()),b(wread());
printf("%lld\n",ask(b)-ask(a-1));
}
}
return 0;
}
不得不说,树状数组区间修改,区间查询比线段树要快一些,但是,下一次,我还是要打线段树!!!
不过,对于 单点修改 区间查询、区间修改 单点查询 还是要膜拜树状数组!!!