树状数组可以实现的功能:
1:单点修改,单点查询&区间查询
(没有找到例题,自己写一个)
数列有n个数字,m次询问,输入1,x,k,第x项加k,输入2,x,输出前k项的和
输入:第一行:n m
第二行:数列里面的n个数字
第3-m+3行:m次询问;
输出:一行一个结果;
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>
#include <math.h>
#define ll long long
using namespace std;
const int N=1e6+9;
ll a[N];//原函数
ll s[N];//树
ll n;
ll lowbit (ll x)
{
return x&(-x);
}
void update(ll m,ll x){ //a[m]+x
for(ll i=m;i<=n;i+=lowbit(i)){
s[i]+=x;
}
return ;
}
ll cha (ll m){//查询1-m项的和
ll sum=0;
for(ll i=m;i>0;i-=lowbit(i)){
sum+=s[i];
}
return sum;
}
int main()
{
ll m;
scanf("%lld %lld",&n,&m);
for(ll i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
update(i,a[i]); //建树
}
ll b,c,d;
while(m--){
scanf("%lld %lld",&b,&c);
if(b==1){
scanf("%lld",&d);
update(c,d);
}
if(b==2){
ll z=cha(c);
printf("%lld\n",z);
}
}
return 0;
}
https://www.luogu.com.cn/problem/P1000
如果要查询区间[n,m]的加和,cha(m)-cha(n-1)即可;
2.区间修改,单点查询;
维护一个差分数组即可
例题:https://www.luogu.com.cn/problem/P3368
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#define ll long long
using namespace std;
int n;
ll a[1000009];
ll s[1000009];
int lowbit(ll x){
return x&(-x);
}
void update(ll m,ll x){
for(int i=m;i<=n;i+=lowbit(i)){
s[i]+=x;
}
return ;
}
ll cha(ll m){
ll sum=0;
for(int i=m;i>0;i-=lowbit(i)){
sum+=s[i];
}
return sum;
}
int main()
{
ll m,i;
a[0]=0;
scanf("%d %lld",&n,&m);
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
update(i,a[i]-a[i-1]);//建树
}
ll c,b,d,f;
while(m--){
scanf("%lld",&c);
if(c==1){ //改值
scanf("%lld%lld%lld",&b,&d,&f);
update(b,f);
update(d+1,-f);
}
else{
scanf("%lld",&d);
ll zz=cha(d);
printf("%d\n",zz);
}
}
return 0;
}
3.区间修改,区间查询
维护的还是差分数组
你有 N 个整数,A 1,A 2,...,AN。 您需要处理两种操作。一种类型的操作是在给定间隔内将一些给定的数字添加到每个数字。另一种是要求给定间隔内的数字总和。
输入
第一行包含两个数字 N 和 Q。1 ≤ N,Q ≤ 100000。
第二行包含 N 个数字,初始值为 A 1、A 2、...、A N。-1000000000 ≤ Ai ≤ 1000000000。
接下来的每一条 Q 行都表示一个操作。
“C a b c”表示将 c 添加到 A a、A a+1、...、Ab 中的每一个。-10000 ≤ c ≤ 10000。
“Q a b”表示查询 A a、A a+1、...、Ab 的总和。
输出
您需要按顺序回答所有 Q 命令。一行一个答案。
样本
输入复制 | 输出复制 |
---|---|
10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 | 4 55 9 15 |
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#define ll long long
using namespace std;
ll n;
ll a[1000009];
ll sum1[1000009];
ll sum2[1000009];
ll lowbit(ll x){
return x&(-x);
}
void update(ll k,ll x){
for(ll i=k;i<=n;i+=lowbit(i)){
sum1[i]+=x;
sum2[i]+=x*(k-1);
}
return ;
}
ll cha (ll k){
// printf("***");
ll sum=0;
for(ll i=k;i>0;i-=lowbit(i)){
sum+=k*sum1[i]-sum2[i];
}
return sum;
}
int main()
{
ll m,mm;
scanf("%lld %lld",&n,&m);
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
update(i,a[i]-a[i-1]);
}
while(m--){
char b[2];
ll c,d,f;
scanf("%s",b);
scanf("%lld %lld",&c,&d);
if(b[0]=='Q'){
ll zz=cha(d)-cha(c-1);
printf("%lld\n",zz);
}
else if(b[0]=='C'){
scanf("%lld",&f);
update(c,f);
update(d+1,-f);
}
}
return 0;
}
结束语:春风得意马蹄疾 伊布拉西莫维奇!