暑假留校参加了ACM的集训,学会了不少新东西,和大家分享一道线段树的入门题吧
个人感觉线段树就是二叉搜索树,这种数据结构把一个区间划分成一些单元区间,每个单元区间都对应线段树中的一个叶结点。使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。
由于我也是看完教程做的推荐的例题,所以很自然的用了线段树这种方法。相比网上其他的教程,我觉得掌握了基本的概念,再看一下这道题的具体应用,应该就能对线段树有一个初步的认识了。
问题是这样的:
#include
#include
using namespace std;
#define MAX_N 50000
string str;
int sum; //记录总兵数
int num[MAX_N+1]={0}; //记录各个兵营的兵数
typedef struct node
{
int left;
int right;
int data;
node* lchild;
node* rchild;
node()
{
left = right = data = 0;
}
}Tree;
Tree* CreateTree(int a,int b)//递归建树
{
Tree* r;
r = (Tree*)malloc(sizeof(Tree));
r->left = a;
r->right = b;
if(a == b)
{
r->data = num[a];
r->lchild = r->rchild = NULL;
}
else
{
int mid = (a+b)>>1;
r->lchild = CreateTree(a,mid);
r->rchild = CreateTree(mid+1,b);
r->data = r->lchild->data + r->rchild->data;
}
return r;
}
void insert(Tree* r,int a,int b)
{
if(r->left == a && r->right == a)
{
r->data += b;
return;
}
int mid = (r->left + r->right)>>1;
if(a <= mid)
{
insert(r->lchild,a,b);
}
else
{
insert(r->rchild,a,b);
}
r->data += b;
}
void find(Tree* r,int a,int b)
{
if(r->left == a && r->right == b)
{
sum += r->data;
return;
}
int mid = (r->left + r->right)>>1;
if(b<=mid)
{
find(r->lchild,a,b);
}
else if(a>mid)
{
find(r->rchild,a,b);
}
else
{
find(r->lchild,a,mid);
find(r->rchild,mid+1,b);
}
}
int main()
{
int t,n,x,y;
int i;
int ca = 0;
scanf("%d",&t);
while(t--)
{
printf("Case %d:/n",++ca);
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&num[i]);
}
Tree* T;
T = CreateTree(1,n);
while(cin>>str)
{
if(str == "Query")
{
sum = 0;
scanf("%d%d",&x,&y);
find(T,x,y);
printf("%d/n",sum);
}
else if(str == "Add")
{
scanf("%d%d",&x,&y);
insert(T,x,y);
}
else if(str == "Sub")
{
scanf("%d%d",&x,&y);
insert(T,x,-y);
}
else
{
break;
}
}
}
return 0;
}