介绍
引入问题:
lowbit(x)
#define lowbit(x) x&(-x)
功能一:单点修改,单点查询,区间查询
一般操作:
tree 存放正常数组 for(i->n){ int x;cin>>x;add(i,x); }
1,单点修改,add(i,x)
2,单点查询,sum(i)
3,区间查询,sum( r )-sum(l-1)
#include<iostream>
using namespace std;
const int N=5e5+5;
int n,m;
int tree[N];
int lowbit(int x)
{
return x&-x;
}
void add(int x,int k)
{
while(x<=n)
{
tree[x]+=k;
x+=lowbit(x);
}
}
int sum(int x)
{
int res=0;
while(x)
{
res+=tree[x];
x-=lowbit(x);
}
return res;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
int x;cin>>x;add(i,x);
}
while(m--)
{
int op,x,y;
cin>>op>>x>>y;
if(op==1) add(x,y);
else{
cout<<sum(y)-sum(x-1)<<endl;
}
}
return 0;
}
功能一:区间修改,单点查询
一般操作:
tree 存放差分数组 for(i->n){ int x;cin>>a[i];add(i,a[i]-a[i-1]); }
1,区间修改,add(l,x) add(r+1,-x)
2,单点查询,sum( i )
#include<iostream>
using namespace std;
const int N=5e5+5;
int n,m;
int tree[N];
int a[N];//当差分数组
int lowbit(int x)
{
return x&-x;
}
void add(int x,int k)
{
while(x<=n)
{
tree[x]+=k;
x+=lowbit(x);
}
}
int sum(int x)
{
int res=0;
while(x)
{
res+=tree[x];
x-=lowbit(x);
}
return res;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
int x;cin>>a[i];add(i,a[i]-a[i-1]);
}
while(m--)
{
int op;cin>>op;
if(op==1) {
int l,r,k;cin>>l>>r>>k;
add(l,k);add(r+1,-k);
}
else{
int x;cin>>x;cout<<sum(x)<<endl;
}
}
return 0;
}
功能三:区间修改,区间查询
一般操作:
第一种 c2[i]=c1[i]*(i-1)
tree1 存放差分数组c1 tree2存c2*(i-1)
1,区间修改,add1(l,x) add1(r+1,-x) add2(l,(l-1)x) add2(r,-(r-1)*x)
2,区间查询,(r *sum1®-sum2®)-((l-1)*sum1(l-1)-sum2(l-1));
简单可证,
那么可以得到以下式子
a[1]+a[2]+…+a[i]
=c[1]+(c[1]+c[2])+…+(c[1]+c[2]+…+c[i])
=i*c[1]+(i-1)*c[2]+…+c[i]
=i*(c[1]+c[2]+…+c[i])-1*c[2]-…-(i-1)*c[i]
于是,我们再搞一个数组c1
那之前的式子就可以表示
对应代码:(r*sum1(r )-sum2(r ))-((l-1)*sum1(l-1)-sum2(l-1));
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m;
int a[N];
ll t1[N],t2[N],c1[N],c2[N];
ll lowbit(int x)
{
return x&-x;
}
void add1(int x,ll k)
{
while(x<=n)
{
t1[x]+=k;
x+=lowbit(x);
}
}
ll sum1(int x)
{
ll ans=0;
while(x)
{
ans+=t1[x];
x-=lowbit(x);
}
return ans;
}
void add2(int x,ll k)
{
while(x<=n)
{
t2[x]+=k;
x+=lowbit(x);
}
}
ll sum2(int x)
{
ll ans=0;
while(x)
{
ans+=t2[x];
x-=lowbit(x);
}
return ans;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
c1[i]=a[i]-a[i-1];c2[i]=(i-1)*c1[i];
add1(i,c1[i]);add2(i,c2[i]);
}
while(m--)
{
int op;cin>>op;
if(op==1)
{
int l,r,x;cin>>l>>r>>x;
add1(l,x);add1(r+1,-x);
add2(l,(l-1)*x);add2(r+1,-r*x);
}
else{
int l,r;cin>>l>>r;
cout<<(r*sum1(r)-sum2(r))-((l-1)*sum1(l-1)-sum2(l-1))<<endl;
}
}
return 0;
}
第二种 c2[i]=c1[i]*i 比较常用
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) x&(-x)
const int N=2e5;
int n,m;
ll a[N],t1[N],t2[N];
void add(int x,ll k)
{
int t=x;
while(x<=n){
t1[x]+=k;t2[x]+=t*k;
x+=lowbit(x);
}
}
ll sum(int x)
{
ll res=0;
int t=x;
while(x){
res+=t1[x]*(t+1)-t2[x];
x-=lowbit(x);
}return res;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a[i];add(i,a[i]-a[i-1]);
}
while (m -- ){
char op;cin>>op;
if(op=='Q'){
int x,y;cin>>x>>y;
cout<<sum(y)-sum(x-1)<<endl;
}else{
int x,y;ll k;cin>>x>>y>>k;
add(x,k);add(y+1,-k);
}
}
return 0;
}