标签:pac sync ini span += init 答案 def 一个
又名二叉索引树,是一种与线段树相似的数据结构
他们能使对一个区间的数修改以及查询的速度提升许多
#include<iostream>
#include<cstdio>
using namespace std;
int tree[2333333];
int sum[233333];
int a[2333333];
int n,m;
#define lowbit(x) (x&(-x))
inline void init()
{
for(int x,i=1;i<=n;i++)
{
cin>>x;
sum[i]=sum[i-1]+x;
tree[i]=sum[i]-sum[i-lowbit(i)];
}
}
inline void add(int a,int val)
{
while(a<=n)
{
tree[a]+=val;
a+=lowbit(a);
}
}
inline int query(int a)
{
int res=0;
while(a)
{
res+=tree[a];
a-=lowbit(a);
}
return res;
}
int main()
{
ios_base::sync_with_stdio(false);
cout.tie(NULL);
cin.tie(NULL);
cin>>n>>m;
init();
for(int i=1;i<=m;i++)
{
int x,y,z;
cin>>x>>y>>z;
if(x == 1)
{
add(y,z);
}
else{
cout<<query(z)-query(y-1)<<‘\n‘;
}
}
}
中间有一个小小的卡常
inline void init()
{
for(int x,i=1;i<=n;i++)
{
cin>>x;
sum[i]=sum[i-1]+x;
tree[i]=sum[i]-sum[i-lowbit(i)];
}
}
该函数能将初始化树状数组的复杂度优化从O(nlogn)->O(n)
#include<iostream>
#include<cstdio>
using namespace std;
int tree[2333333];
int c[2333333];
int n,m;
inline int lowbit(int x) {return x&-x;}
inline void add(int a,int val)
{
while(a<=n)
{
tree[a]+=val;
a+=lowbit(a);
}
}
inline int query(int a)
{
int res=0;
while(a)
{
res+=tree[a];
a-=lowbit(a);
}
return res;
}
int main()
{
ios_base::sync_with_stdio(false);
cout.tie(NULL);
cin.tie(NULL);
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>c[i];
}
for(int i=1;i<=m;i++)
{
int l,x,y,z;
cin>>l;
if(l == 1)
{
cin>>x>>y>>z;
add(x,z);
add(y+1,-z);
}
else
{
cin>>x;
int U=query(x)+c[x];
cout<<U<<‘\n‘;
}
}
}
#include<iostream>
#include<cstdio>
using namespace std;
const long long maxn=1e5+5;
long long n,m;
long long sum[maxn];
long long tree[2][maxn];
inline long long lowbit(long long x) {return x&-x;}
inline void add(long long k,long long a,long long val)
{
while(a<=n)
{
tree[k][a]+=val;
a+=lowbit(a);
}
}
inline long long query(long long k,long long a)
{
long long res=0;
while(a)
{
res+=tree[k][a];
a-=lowbit(a);
}
return res;
}
int main()
{
cin>>n>>m;
long long x;
for(long long i=1;i<=n;i++)
{
cin>>x;
sum[i]=sum[i-1]+x;
}
for(long long i=1,x,y,z,g;i<=m;i++)
{
cin>>x>>y>>z;
if(x == 1)
{
cin>>g;
add(1,y,g);
add(1,z+1,-g);
add(0,y,y*g);
add(0,z+1,-(z+1)*g);
}
else{
cout<<(sum[z]+(z+1)*query(1,z)-query(0,z))-(sum[y-1]+y*query(1,y-1)-query(0,y-1))<<‘\n‘;
}
}
}
对单点查询=访问原值+b树状数组前缀和
所以区间查询相当于对多个点进行单点查询
那么a前缀和整体增加值为
\(\sum_{i=1}^x{\sum_{j=1}^i{b[j]}}\)
\(\sum_{i=1}^x{\sum_{j=1}^i{b[j]}} = \sum_{i=1}^x{(x-i+1)*b[i]} = (x+1)\sum_{i=1}^xb[i] - \sum_{i=1}^x{i*b[i]}\)
所以我们增加一个树状数组,维护 \(i*b[i]\)的前缀和\(\sum_{i=1}^x{i*b[i]}\)
另外我们维护原数组前缀和sum,对于每条 Q l r
可得出
访问原值前缀和与上述两个树状数组的值在套用上式与另一端点作差即可得出答案
标签:pac sync ini span += init 答案 def 一个
原文地址:https://www.cnblogs.com/-Iris-/p/13278466.html