来源:点击打开链接
这个题有两种解法,树状数组&线段树,当然这也是这种题目的通常状况,线段树和划分树普适性更强一些,但线段树显然更简单,比如我印象深刻的有2012长春赛区区域网络赛的第一道题,快速的做法是用一个三维的树状数组,无解的怨念啊。。
这个题没什么要注意的,寻找第I到J个的和也很简单,用find_add(J)-find_add(I-1)就行了。。。。这两道题很适合初学者了解树状数组。
感觉最主要的便是神奇的lowbit函数了,类似的讲解网上遍地都是,不多说了。。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int c[50005];
int N;
int lowbit(int x)
{
return x&(-x);
}
int query_add(int x)
{
int result=0;
for(int i=x;i>0;i-=lowbit(i))
{
result+=c[i];
}
return result;
}
void modify_add(int pos,int delta)
{
for(int i=pos;i<=N;i+=lowbit(i))
{
c[i]+=delta;
}
}
void modify_sub(int pos,int delta)
{
for(int i=pos;i<=N;i+=lowbit(i))
{
c[i]-=delta;
}
}
int main()
{
int testcase;
char a[30];
scanf("%d",&testcase);
for(int p=1;p<=testcase;p++)
{
memset(c,0,sizeof(c));
int packnum,x,y;
scanf("%d",&packnum);
N=packnum;
for(int i=1;i<=packnum;i++)
{
int temp;
scanf("%d",&temp);
modify_add(i,temp);
}
printf("Case %d:\n",p);
while(true)
{
scanf("%s",&a);
if(a[0]=='E')
break;
else if(strcmp("Query",a)==0)
{
scanf("%d%d",&x,&y);
printf("%d\n",query_add(y)-query_add(x-1));
}
else if(strcmp("Add",a)==0)
{
scanf("%d%d",&x,&y);
modify_add(x,y);
}
else if(strcmp("Sub",a)==0)
{
scanf("%d%d",&x,&y);
modify_sub(x,y);
}
}
}
return 0;
}