版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/84729117
题目链接:哆啦A梦传送门
题解:
参考链接:https://www.cnblogs.com/TenosDoIt/p/3453089.html
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=50010;
struct node{
int val;
}segtree[maxn*4];
int arr[maxn];
/*
root:当前线段树的根节点下标
arr: 用来构造线段树的数组
istart:数组的起始位置
iend:数组的结束位置
*/
void build(int root,int istart,int iend)
{
if(istart==iend){ ///叶子节点
segtree[root].val=arr[istart];
}
else{
int mid=(istart+iend)/2;
build(root*2,istart,mid); ///递归构造左子树
build(root*2+1,mid+1,iend);///递归构造右子树
///根据左右子树根节点的值,更新当前根节点的值
segtree[root].val=segtree[root*2].val+segtree[root*2+1].val;
}
}
/*
功能:线段树的区间查询
root:当前线段树的根节点下标
[nstart, nend]: 当前节点所表示的区间
[qstart, qend]: 此次查询的区间
*/
int query(int root,int nstart,int nend,int qstart,int qend)
{
///查询区间和当前节点区间没有交集
if(qstart>nend||qend<nstart)
return 0;
///当前节点区间包含在查询区间内
if(qstart<=nstart&&qend>=nend)
return segtree[root].val;
///分别从左右子树查询,返回两者查询结果的较小值
int mid=(nstart+nend)/2;
return query(root*2,nstart,mid,qstart,qend)
+query(root*2+1,mid+1,nend,qstart,qend);
}
/*
功能:更新线段树中某个叶子节点的值
root:当前线段树的根节点下标
[nstart, nend]: 当前节点所表示的区间
index: 待更新节点在原始数组arr中的下标
addVal: 更新的值(原来的值加上addVal)
*/
void updataone(int root,int nstart,int nend,int index,int addval)
{
if(nstart==nend)
{
if(index==nstart) ///找到了相应的节点,更新之
{
segtree[root].val+=addval;
return;
}
}
int mid=(nstart+nend)/2;
if(index<=mid) ///在左子树中更新
updataone(root*2,nstart,mid,index,addval);
else
updataone(root*2+1,mid+1,nend,index,addval);///在右子树中更新
///根据左右子树的值回溯更新当前节点的值
segtree[root].val=segtree[root*2].val+segtree[root*2+1].val;
}
char str[10];
int main()
{
int ncase,n,x,y;
scanf("%d",&ncase);
int T=0;
while(ncase--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&arr[i]);
build(1,1,n);
printf("Case %d:\n",++T);
while(scanf("%s",str))
{
if(strcmp(str,"End")==0) break;
else if(strcmp(str,"Query")==0)
{
scanf("%d%d",&x,&y);
printf("%d\n",query(1,1,n,x,y));
}
else if(strcmp(str,"Add")==0)
{
scanf("%d%d",&x,&y);
updataone(1,1,n,x,y);
}
else if(strcmp(str,"Sub")==0)
{
scanf("%d%d",&x,&y);
updataone(1,1,n,x,-y);
}
}
}
return 0;
}
参考神犇kuangbin模板,
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=50010;
struct node{
int l,r;
int val;
}segtree[maxn*4]; ///每个节点表示的范围 值
int arr[maxn];
void build(int root,int istart,int iend) ///建树
{
segtree[root].l=istart;///存储此节点的左右范围
segtree[root].r=iend;
if(istart==iend){
segtree[root].val=arr[istart];
}
else{
int mid=(istart+iend)>>1;
build(root<<1,istart,mid);
build(root<<1|1,mid+1,iend);
segtree[root].val=segtree[root<<1].val+segtree[root<<1|1].val;
}
}
int query(int root,int qstart,int qend)
{
if(qstart==segtree[root].l&&qend==segtree[root].r) ///此节点恰好满足
return segtree[root].val;
int mid=(segtree[root].l+segtree[root].r)>>1;
if(qend<=mid) return query(root<<1,qstart,qend); ///在左子树
else if(qstart>mid) return query(root<<1|1,qstart,qend); ///在右子树
return query(root<<1,qstart,mid)+query(root<<1|1,mid+1,qend);
}
void updataone(int root,int index,int addval) ///在位置index加上值addval
{
///在此节点加上
segtree[root].val+=addval;
if(segtree[root].l==index&&segtree[root].r==index) return;
int mid=(segtree[root].l+segtree[root].r)>>1;
if(index<=mid) ///在左子树
updataone(root<<1,index,addval);
else
updataone(root<<1|1,index,addval);
}
char str[10];
int main()
{
int ncase,n,x,y;
scanf("%d",&ncase);
int T=0;
while(ncase--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&arr[i]);
build(1,1,n);
printf("Case %d:\n",++T);
while(scanf("%s",str))
{
if(strcmp(str,"End")==0) break;
else if(strcmp(str,"Query")==0)
{
scanf("%d%d",&x,&y);
printf("%d\n",query(1,x,y));
}
else if(strcmp(str,"Add")==0)
{
scanf("%d%d",&x,&y);
updataone(1,x,y);
}
else if(strcmp(str,"Sub")==0)
{
scanf("%d%d",&x,&y);
updataone(1,x,-y);
}
}
}
return 0;
}