线段树求和

  线段树如下图所示,是一个二叉搜索树,记录了a到b的一些信息,比如在这里我们记录a到b所有节点数的总和。下图所示:根节点是1-4,这个节点可以分为1-2,3-4两个子节点,同理,子节点继续往下面分裂。

例题:

在示例代码中,

1.a数组存放这个线段树,每个节点的父节点(加)或它前面的兄弟节点(减,有时候找不到,直接找到0,就是没有)可以通过lowbit计算

  具体展开关系:1->2;2->4;3->4;4->8;5->6;6->8;7->8;

2.lowbit:

  正数与它的负数的与,负数的二进制是正数取反再加一

 3.getsum

  获取0-t的总和,8(4)记录了0-8的所有值,所以直接可求

  7:记录了自己,所以要计算6(记录了5-6),4(0-4)

 4.代码贴在这主要为了遇到的时候快速复制粘贴

#include <stdio.h>
#include <string.h>
#include<math.h>
int a[50005];
int n;
int lowbit(int t){
	return t&(-t);
}
void insert(int t,int d){
	while(t<=n){
		a[t]+=d;
		t=t+lowbit(t);
	}
}
__int64 getsum(int t){
	__int64 sum=0;
	while(t>0){
		sum+=a[t];
		t=t-lowbit(t);
	}
	return sum;
}
int main(){
	int T,i,j,k,t;
	scanf("%d",&T);
	t=0;
	while(T--){
		memset(a,0,sizeof(a));
		scanf("%d",&n);
		for(i=1;i<=n;i++){
			scanf("%d",&k);
			insert(i,k);
		}
		char str[10];
		scanf("%s",str);
		printf("Case %d:\n",++t);
		while(strcmp(str,"End")!=0){
			int x,y;
			scanf("%d%d",&x,&y);
			if(strcmp(str,"Query")==0)
				printf("%lld\n",getsum(y)-getsum(x-1));
			else if(strcmp(str,"Add")==0)
				insert(x,y);
			else if(strcmp(str,"Sub")==0)
				insert(x,-y);
			scanf("%s",str);
		}
	}
	return 0;
}

  

posted @ 2019-03-13 17:41  郑御前  阅读(217)  评论(0编辑  收藏  举报