题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166
线段树第一题~
分割线///
线段树:一种二叉搜索树,类似于区间树,各个字节点为线段或者单元区间,能基本保证每个操作的复杂度为O(logn).对于一个非叶节点区间[a,b],其左儿子对应的区间为[a,(a+b)/2],右儿子对应的区间为[(a+b)/2+1,b],因此该树也是平衡二叉树,叶节点个数为b-a+1.
线段树的基本操作:
1>线段树的构造
由于树本身是一种递归结构,所以构造树也是一种递归的思想,下面可以看成伪代码
function 构造区间为[a,b]的线段树
if 区间内元素为1,即b-a=0
区间的元素值就是这个元素,最小值也即这个元素 (eg:[1,10]中,[1,1],[2,2],[3,3]区间值最小值是1,2,3)
else
把区间一分为2,构造[a,(a+b)/2]和[(a+b)/2+1,b]区间的数
更新结点之间信息
区间的信息(sum,min)=(sum,min)(左儿子+右儿子).
2>区间查询
function 查询区间[a,b]的信息
if 区间的左值==a&&区间的右值==b
取得相应信息,return;
int mid=(lson+rson)/2; //mid为分隔点
if(b<=mid)
查询左儿子部分的信息
if(a>mid)
查询右儿子部分信息
else
{
查询[a,mid];
查询[mid+1,b];
}
}
此题用的静态数组做,也可以用链表来做~
AC code:
#include<stdio.h>
#include<iostream>
#include<cstring>
using namespace std;
struct T
{
int lson,rson,n; //结构体定义左右结点区间
}Tree[150001];
int sum;
void InitTree(int l,int r,int k)
{
if(l==r)
{
Tree[k].lson=l;
Tree[k].rson=r;
Tree[k].n=0;
return ;
}
else
{
Tree[k].lson=l;
Tree[k].rson=r;
Tree[k].n=0;
int mid=(l+r)/2;
InitTree(l,mid,2*k); //构造左半区间
InitTree(mid+1,r,2*k+1); //构造右半区间
}
}
void Insert(int num,int add,int k)
{
if(Tree[k].lson==num&&Tree[k].rson==num) //找到单元区间,增加add
{
Tree[k].n+=add;
return;
}
else
{
int mid=(Tree[k].lson+Tree[k].rson)/2;
if(num>mid) //大于中值,根据树的结构,在右边查找
Insert(num,add,2*k+1);
else
Insert(num,add,2*k); //小于中值,在左树查找
}
Tree[k].n=Tree[2*k].n+Tree[2*k+1].n; //更新结点值
}
void Query(int s,int d,int k)
{
if(Tree[k].lson==s&&Tree[k].rson==d) //找到区间,把值存到sum中
{ sum=sum+Tree[k].n; return;}
else
{
int mid=(Tree[k].lson+Tree[k].rson)/2;
if(d<=mid) //尾部小于中值,则查找区间为树的左边
Query(s,d,2*k);
else if(s>mid) //起点大于中值,则查找区间为树的右边
Query(s,d,2*k+1);
else //划分区间,合并值
{
Query(s,mid,2*k); //s~mid
Query(mid+1,d,2*k+1); //mid+1~d
}
}
}
int main()
{
int i,j,test,num,t,flag,dex,dey,Count=0;
char str[10];
scanf("%d",&test);
while(test--)
{
Count++;
flag=1;
scanf("%d",&num);
InitTree(1,num,1);
for(i=1;i<=num;++i)
{
scanf("%d",&t);
Insert(i,t,1);
}
cin>>str;
if(str[0]=='E') { flag=0; continue;}
cout<<"Case "<<Count<<":"<<endl;
while(1)
{
sum=0;
if(str[0]=='E') { flag=0; break;}
scanf("%d%d",&dex,&dey);
if(str[0]=='Q')
{
Query(dex,dey,1);
printf("%d\n",sum);
}
if(str[0]=='A')
Insert(dex,dey,1);
if(str[0]=='S')
Insert(dex,-dey,1);
cin>>str;
}
if(!flag) continue;
}
}