您的位置:首页 > 其它

HDU 1166:敌兵布阵(线段树入门)

2017-07-06 01:16 489 查看
点击打开题目链接

线段树入门,单点更新,区间查询。

#include<stdio.h>
#include<string.h>

#define lchild left,mid,root<<1 //左区间参数
#define rchild mid+1,right,root<<1|1 //右区间参数

const int maxn=50010;
int sum[maxn<<2];

void Push_Up(int root) //更新当前节点
{
sum[root] = sum[root<<1]+sum[root<<1|1];
}
//递归构建线段树
void Build(int left,int right,int root)
{
if(left == right) //左右边界一样
{
scanf("%d",&sum[root]); //输入节点的士兵数目
return;
}
int mid = (left+right)>>1;
//递归构建左区间
//递归构建右区间
Build(lchild);
Build(rchild);
Push_Up(root); //计算left~right这个区间的士兵数量
}
//当Add或Sub i,j的时候更新值,更新目标节点的值在更新他所在区间的值。
void Update(int left,int right,int root,int target,int add)
{
if(left == right)
{
sum[root] += add;
return;
}
int mid = (left+right)>>1;
if(target<=mid) Update(lchild,target,add); //说明这点在左区间
else Update(rchild,target,add); //说明这点在右区间
//处理完root的左右区间,更新当前节点的值
Push_Up(root);
}
//区间查询,查询区间(L,R)之间的所有士兵
int Query(int L,int R,int left,int right,int root)
{
//当前节点的区间在所查询的区间之内,返回区间和值
if(L<=left && right<=R)
{
return sum[root];
}
int ans = 0;
int mid = (left+right)>>1;
//要查询的区间的右边界小于mid,说明要查询的区间位于当前节点的左区间
if(R<=mid) ans += Query(L,R,lchild);
else if(L>mid) ans += Query(L,R,rchild);
else
{
ans += Query(L,R,lchild);
ans += Query(L,R,rchild);
}
return ans;
}
int main()
{
int T,n,t=0,i,j;
scanf("%d",&T); //T组测试数据
while(T--)
{
printf("Case %d:\n",++t);
scanf("%d",&n);
Build(1,n,1);
while(1)
{
char str[50];
scanf("%s",str);
if(!strcmp(str,"End")) break;
else
{
scanf("%d%d",&i,&j);
if(!strcmp(str,"Add"))
{
Update(1,n,1,i,j);
}
else if(!strcmp(str,"Sub"))
{
Update(1,n,1,i,-j);
}
else
{
int ans = Query(i,j,1,n,1);
printf("%d\n",ans);
}
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: