敌兵布阵(HDOJ1166)

最近一个周在学习线段树,晒晒学习成果。

线段树结构:以最大区间是10为例

                                   1【1                        ,                    10】  
                                   /                                                         \
                            2【1,5】                                                3【6,10】
                            /         \                                                 /              \
                     4【1,3】     5【4,5】                                6【6,8】        7【9,10】
                    /     \            /      \                                 /         \           /        \
          8【1,2】9【3,3】10【4,4】11【5,5】       12【6,7】13【8,8】14【9,9】15【10,10】
           /    \                                                     /         \
   16【1,1】17【2,2】                             22【6,6】23【7,7】

  叶子节点记录最原始的数据,其他节点则记录这个区间的数据(或者是这个区间的和,或者是最大值或者是最小值,根据题目而定)。

 原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 (区间求和)

  summary(int index)函数用来计算第index个节点所表示的区间内数据的和;

  build(int l,int r,int index)函数用来建造线段树,把原始数据填入的同时计算各区间的数据和;

  update(int l,int r,int index,int updateindex,int updatedata)更新最原始数据的同时,从线段树下面开始向上更新各区间的结果;

  query(int l,int r,int index,int queryL,int queryR)查询该区间的数据和。

 下面是源代码:

#include<iostream>
using namespace std;
#define lson l,mid,index<<1
#define rson mid+1,r,index<<1|1
#define max 55555
int num[max<<2];
void summary(int index)
{
	num[index]=num[index<<1]+num[index<<1|1];
}
void build(int l,int r,int index)
{
  if(l==r)//叶子节点读入数据
  {
    scanf("%d",&num[index]);
	return ;
  }
  int mid=(l+r)>>1;
  build(lson);//构建左孩子
  build(rson);//构建右孩子
  summary(index);
}
void update(int l,int r,int index,int updateindex,int updatedata)
{
	if(l==r)
	{
	  num[index]+=updatedata;
	  return ;
	}
        int mid=(l+r)>>1;
	if(updateindex<=mid)
		update(lson,updateindex,updatedata);
	else
		update(rson,updateindex,updatedata);
	summary(index);
}
int query(int l,int r,int index,int queryL,int queryR)
{
	if(queryL<=l&&queryR>=r)
	{
	  return num[index];
	}
	int sum=0;
	int mid=(l+r)>>1;
	if(queryL<=mid)//把查询区间分为两段,一段是(queryL,mid),另一段是(mid+1,queryR)
		sum+=query(lson,queryL,queryR);
	if(queryR>mid)
		sum+=query(rson,queryL,queryR);
	return sum;
}
int main()
{
	int count,a,b,c;
	scanf("%d",&count);
	char ch[6];
	for(int i=1;i<=count;i++)
	{
	  scanf("%d",&a);;
	  build(1,a,1);
	  cout<<"Case "<<i<<":"<<endl;
	  while(scanf("%s",ch))
	  {
		if(ch[0]=='E')break;
	    scanf("%d %d",&b,&c);
		if(ch[0]=='Q')
			printf("%d\n",query(1,a,1,b,c));
		else if(ch[0]=='A')
			update(1,a,1,b,c);
		else if(ch[0]=='S')
			update(1,a,1,b,-c);
	  }
	}
}

 

posted @ 2013-03-30 15:31  supersnow0622  Views(130)  Comments(0)    收藏  举报