题目描述
给定一个长度为n(n<=100000),初始值都为0的序列,x(x<=10000)次的修改某些位置上的数字,每次加上一个数,然后提出y (y<=10000)个问题,求每段区间的和。时间限制1秒。
输入输出格式
输入格式:第一行1个数,表示序列的长度n
第二行1个数,表示操作的次数w
后面依次是w行,分别表示加入和询问操作
其中,加入用x表示,询问用y表示
x的格式为"x a b" 表示在序列a的位置加上b
y的格式为"y a b" 表示询问a到b区间的加和
输出格式:每行一个数,分别是每次询问的结果
输入输出样例
嗯。。。递归版的线段树。。。
代码如下
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 410000
using namespace std;
char ch;
int n,m,x,y,ans;
struct Tree
{
int l,r,w,f;
}tree[N];
void build(int k,int l,int r)
{
tree[k].l=l,tree[k].r=r;
if(tree[k].l==tree[k].r)
{
tree[k].w=0;
return ;
}
int m=(l+r)>>1;
build(k<<1,l,m);
build(k<<1|1,m+1,r);
}
void change_point(int k)
{
if(tree[k].l==tree[k].r)
{
tree[k].w+=y;
return ;
}
int m=(tree[k].r+tree[k].l)>>1;
if(x<=m) change_point(k<<1);
else change_point(k<<1|1);
tree[k].w=tree[k<<1].w+tree[k<<1|1].w;
}
void ask_interval(int k)
{
if(tree[k].l>=x&&tree[k].r<=y)
{
ans+=tree[k].w;
return ;
}
int m=(tree[k].r+tree[k].l)>>1;
if(x<=m) ask_interval(k<<1);
if(y>m) ask_interval(k<<1|1);
}
int main()
{
scanf("%d%d",&n,&m);
build(1,1,n);
while(m--)
{
ans=0;
cin>>ch;
scanf("%d%d",&x,&y);
if(ch=='x')
change_point(1);
else
{
ask_interval(1);
printf("%d\n",ans);
}
}
return 0;
}

本文介绍了一种使用线段树解决区间更新与查询问题的方法。通过递归实现线段树的构建、区间更新及区间求和查询,有效地处理大规模序列的操作。适用于序列长度较大且频繁进行区间操作的场景。
626

被折叠的 条评论
为什么被折叠?



