本人水平有限,题解不到为处,请多多谅解
本蒟蒻谢谢大家观看
题目:
Problem A: 线段树之Sum
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 187 Solved: 130
[Submit][Status][Web Board]
Description
给定一数列,规定有两种操作,一是修改某个元素,二是求区间的连续和。
注意:初始序列全部为0。
输出时,只有k=1才输出,否则继续运行。
Input
输入数据第一行包含两个正整数n,m(n<=100000,m<=500000),以下是m行,
每行有三个正整数k,a,b(k=0或1, a,b<=n).
k=0时表示将a处数字加上b,k=1时表示询问区间[a,b]内所有数的和。
每行有三个正整数k,a,b(k=0或1, a,b<=n).
k=0时表示将a处数字加上b,k=1时表示询问区间[a,b]内所有数的和。
Output
对于每个询问输出对应的答案。
Sample Input
10 20
0 1 10
1 1 4
0 6 6
1 4 10
1 8 9
1 4 9
0 10 2
1 1 8
0 2 10
1 3 9
0 7 8
0 3 10
0 1 1
1 3 8
1 6 9
0 5 5
1 1 8
0 4 2
1 2 8
0 1 1
Sample Output
10
6
0
6
16
6
24
14
50
41
HINT
因为初始序列为0,所以不需要再来建树。
此题为线段树模板题,
change(p,l,r,x,v)含义分别是:
p 代表当前树的编号 ,l 代表左序号,r 代表右序号,x 代表要修改的位置——即需要修改的序号,v 代表要修改的值。
query(int p,int l,int r,int x,int y)含义分别是:
p 代表当前树的编号 ,l 代表当前左序号,r 代表当前右序号,x 代表查询左序号,y 代表查询右序号。
因为修改操作不需要输出答案,所以递归函数使用void , 查询操作要求输出答案,所以递归函数使用int 。
code:
#include<bits/stdc++.h> #define maxn 100000 #define maxnn 400000 using namespace std; int n,m; int a[maxn]; inline int read(){ int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-')f=-1; ch=getchar(); } while(ch<='9'&&ch>='0'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } struct segment{ int sum[maxnn]; #define ls p*2 #define rs p*2+1 #define mid (l+r)/2//注意:这里不能写成 #define mid l+r>>1 否则报错 segment(){memset(sum,0,sizeof(sum));} void update(int p){ sum[p]=sum[ls]+sum[rs];//更新函数,依据题意为累加 //当前区间为下面两个子区间之和 } void build (int p,int l,int r){//建树 if(l==r){ sum[p]=a[l];//当左边序号与右边序号相等时,就直接建树 return ; } build(ls,l,mid);//找左区间 build(rs,mid+1,r);//找右区间 update(p);//更新 } void change(int p,int l,int r,int x,int v){//更改操作(修改元素) if(l==r&&l==x){//当左序号与右序号相等,并且要修改的位置x与左序号相等 sum[p]+=v;//依据题意:把a+b,即要修改的元素v加上 return ; } if(x<=mid)change(ls,l,mid,x,v);//当要修改的位置x在mid左时,就递归左区间 if(x>mid)change(rs,mid+1,r,x,v);//当要修改的位置在mid右时,就递归右区间 update(p);//更新 } int query(int p,int l,int r,int x,int y){//区间查询操作(统计答案) if(l>y||r<x)return 0;//如果查询区间与当前区间完全无交集,直接return 0; if(x<=l&&r<=y)return sum[p];//如果查询区间完全包含当前区间,直接返回当前值 //因为我们是先访问当前区间,再查询当前区间,相当于左右子区间的值即可表示其父亲区间 int ans=0; if(x<=mid)ans+=query(ls,l,mid,x,y);//查询 x →mid区间,并求和 if(y>mid)ans+=query(rs,mid+1,r,x,y);//查询 mid →y区间,并求和 update(p);//更新 return ans;//返回区间和的值 } }kd; int main(){ n=read(); m=read(); for(int i=1;i<=n;i++) a[i]=0; for(int i=1,k,a,b;i<=m;i++){ k=read(),a=read(),b=read(); if(k==0)kd.change(1,1,n,a,b);//从序号1开始,1~n为当前总序号,a为修改位置,b为需要修改的值 if(k==1)printf("%d ",kd.query(1,1,n,a,b));//从序号1开始,1~n为当前总序号,a~b为查询序号 } return 0; }