您的位置:首页 > 其它

CODEVS 1080线段树练习

2016-11-01 22:31 387 查看
#include<stdio.h>
#include<iostream>
using namespace std;
int n,m,sum[400001],a[100010],x,y,z;
int dfs(int o,int l,int r){//以sum数组构建线段树,节点o,这个节点为从l到r的和
int mid=(l+r)/2;//中点
if(l==r) return sum[o]=a[l];//叶节点 该点值即为自己(长度为1)
else return sum[o]=dfs(2*o,l,mid)+dfs(2*o+1,mid+1,r);//o点的值为左子树+右子树
}
void add(int o,int l,int r){//给 y 位置加上 z,从上向下递归,如果该节点包含y位置,这个节点就要加z
int mid=(l+r)/2;//中点
sum[o]+=z;
if(l==r) return;//递归到叶节点,返回
if(y<=mid) add(2*o,l,mid);//y在左半段
else add(2*o+1,mid+1,r);//y在右半段
return;//返回
}
int ssum(int o,int l,int r){//求[y,z]区间之和
int mid=(l+r)/2,ans=0;//中点
if(y<=l&&r<=z) return sum[o];//当搜索到一个区间[l,r]被[y,z]包含时立刻return
if(y<=mid) ans+=ssum(2*o,l,mid);//[y,z]横跨mid时
if(mid+1<=z) ans+=ssum(2*o+1,mid+1,r);//[y,z]横跨mid时
return ans;
}
int main(){
freopen("1080.in","r",stdin);
freopen("1080.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
dfs(1,1,n);
cin>>m;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
if(x==1) add(1,1,n);
if(x==2) printf("%d\n",ssum(1,1,n));
}
return 0;
}


题解:线段树基础入门,详见备注。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: