http://acm.hdu.edu.cn/showproblem.php?pid=1166
***********************************************************
本人做的第一道线段树的题,纪念一下吧
***********************************************************
/**********************************
Accepted 1166 46MS 2476K 1572 B C++
**********************************/
#include<iostream>
using namespace std;
struct node
{
int left,right,mid;
int num;//该结点士兵数
}a[150000];//通常3*n的空间就ok
int st[50010],sum;
void creat(int s,int t,int step)//建树
{
a[step].left=s;
a[step].right=t;
a[step].mid=(s+t)/2;
if(s==t){
a[step].num=st[t];
return ;
}
creat(s,a[step].mid,2*step);
creat(a[step].mid+1,t,2*step+1);
a[step].num=a[2*step].num+a[2*step+1].num;
}
void add(int ans1,int ans2,int step)//Sub & Add函数
{
a[step].num+=ans2;//为啥要放在这里?因为每棵子树都是包含关系,看看线段树就知道了,【这里每个节点都保存了子树士兵的和】
if(a[step].left==a[step].right){return ;}
if(ans1<=a[step].mid)
add(ans1,ans2,2*step);
else
add(ans1,ans2,2*step+1);
}
void find(int s,int t,int step)
{
if(s==a[step].left && t==a[step].right){sum+=a[step].num;return ;}//询问时遇到匹配的线段就return!
if(t<=a[step].mid)
find(s,t,2*step);
else
if(s>a[step].mid)
find(s,t,2*step+1);
else
{
find(s,a[step].mid,2*step);
find(a[step].mid+1,t,2*step+1);
}
}
int main()
{
freopen("a.txt","r",stdin);
int ca;
while(scanf("%d",&ca)!=EOF)
{
int nca;
for(nca=1;nca<=ca;nca++)
{
printf("Case %d:\n",nca);
int n;
scanf("%d",&n);
int i;
for(i=1;i<=n;i++)
scanf("%d",&st[i]);
creat(1,n,1);
char str[10];
while(scanf("%s",str))
{
if(str[0]=='E')break;
int ans1,ans2;
scanf("%d%d",&ans1,&ans2);
if(str[0]=='A')
add(ans1,ans2,1);
if(str[0]=='S')//减的时候可以取负再调用add函数
{
ans2=-ans2;
add(ans1,ans2,1);
}
if(str[0]=='Q')
{
sum=0;
find(ans1,ans2,1);
printf("%d\n",sum);
}
}
}
}
return 0;
}
贴一个树状数组的
#include <iostream>
using namespace std;
int tree[50005];
int n;
int Lowbit(int k)
{
return k&(-k);
//return k&(k^(k-1));
}
int Sum(int a)
{
int result = 0;
while(a != 0)
{
result += tree[a];
a -= Lowbit(a);
}
return result;
}
void Modify(int a,int c,int n)
{
while(a<=n)
{
tree[a] += c;
a +=Lowbit(a);
}
}
int main()
{freopen("a.txt","r",stdin);
int i,j,k;
int Tcase=0;
int Case;
char ch[10];
scanf("%d",&Case);
while(Case--)
{
printf("Case %d:\n",++Tcase);
memset(tree,0,sizeof(tree));
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&k);
Modify(i,k,n);
}
while(1)
{
scanf("%s",&ch);
if(ch[0]=='E')break;
scanf("%d%d",&i,&j);
if(ch[0]=='Q')
printf("%d\n",Sum(j)-Sum(i-1));
else if(ch[0]=='A')
Modify(i,j,n);
else if(ch[0]=='S')
Modify(i,-j,n);
}
}
return 0;
}