初学树状数组
树状数组主要掌握好三个函数,在这里我把lowbit函数直接写在另外两个函数里,单独拿出来也可以,如下
int lowbit(int x)
{
return x&(-x);
}
int query(int x)
{
int ans=0;
for(;x;x-=x&(-x))
ans+=c[x];
return ans;
}
void add(int x,int y)
{
for(;x<maxn;x+=x&(-x))
c[x]+=y;
}
在add函数中要注意,for循环中x<maxn的条件,不能写成x<n,否则样例都过不去,主要体现在y为负,即减法的时候出错
并且注意函数中用的是c数组,需要在输入数据时。利用add函数完善c数组
例题
敌兵布阵问题
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令
对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。
代码如下
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<queue>
using namespace std;
const int maxn=5e4+5;
int T;
int n;
int arr[maxn];
int c[maxn];
int query(int x)
{
int ans=0;
for(;x;x-=x&(-x))
ans+=c[x];
return ans;
}
int add(int x,int y)
{
for(;x<maxn;x+=x&(-x))
c[x]+=y;
}
int main()
{
scanf("%d",&T);
for(int t=1;t<=T;t++){
scanf("%d",&n);
memset(c,0,sizeof(c));
memset(arr,0,sizeof(arr));
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);
add(i,arr[i]); //函数中要用的是c数组,因此要把arr数组转化成c数组
}
printf("Case %d:\n",t);
char str[20];
while(scanf("%s",str)){
if(str[0]=='E')
break;
int x,y;
scanf("%d%d",&x,&y);
int num=0;
if(str[0]=='Q'){
num=query(y)-query(x-1);
printf("%d\n",num);
}
else if(str[0]=='A'){
add(x,y);
}
else if(str[0]=='S'){
add(x,(-y));
}
}
}
return 0;
}