您的位置:首页 > 理论基础 > 数据结构算法

数据结构 (线段树入门) HDU 1166 敌兵布阵(单点更新)

2016-08-16 16:16 344 查看
写的第一个线段树题。

题意:对一个数列a1,a2……an,

进行3种操作

1.在数列中 i 处加 j 

2.在数列中 i 处减 j

3.询问求数列 i-j 处的和

解法:线段树(第一次做,看程序再加上 查看建树,就很容易明白线段树是什么东西了)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
using namespace std;
const int maxn=50010;
int sum[maxn<<2];
void PushUP(int rt){
sum[rt]= sum[rt<<1] +sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
if(l==r)
{//叶子节点,输入
scanf("%d",&sum[rt]);
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);//向左建树
build(m+1,r,rt<<1|1);//向右建树
PushUP(rt);//累计和往上填
}
void update(int p,int add,int l,int r,int rt)
{///p 处 数值增加 add
if(l==r){
sum[rt]+=add;
return;
}
int m=(l+r)>>1;
if(p<=m)
update(p,add,l,m,rt<<1);//去左边
else update(p,add,m+1,r,rt<<1|1);
PushUP(rt);//叶子加完之后逐渐向上更新
}
int query(int L,int R,int l,int r,int rt)
{//询问 L到R 位置的和
// ↓可以减少查询所花时间
if(L<=l && r<=R) //恰好在范围内的,直接返回范围内的和
return sum[rt];

int m=(l+r)>>1;
int ret=0;
if(L<=m) ret+=query(L,R,l,m,rt<<1);
if(R>m)	ret+=query(L,R,m+1,r,rt<<1|1);
return ret;
}
int main()
{
int cas=1,T,n;
scanf("%d",&T);
while(T--)
{
printf("Case %d:\n",cas++);
scanf("%d",&n);
build(1,n,1);
/*查看建树
for(int i=1;i<=3*n;i++)
printf("%d--",sum[i]);*/
char op[10];
while(scanf("%s",op)){
if(op[0]=='E') //结束
break;
int a,b;
scanf("%d%d",&a,&b);
if(op[0]=='Q') //询问
printf("%d\n",query(a,b,1,n,1));
else if(op[0]=='S') //减去
update(a,-b,1,n,1);
else if(op[0]=='A') //增加
update(a,b,1,n,1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: