秋实大哥与线段树
Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others)
“学习本无底,前进莫徬徨。” 秋实大哥对一旁玩手机的学弟说道。
秋实大哥是一个爱学习的人,今天他刚刚学习了线段树这个数据结构。
为了检验自己的掌握程度,秋实大哥给自己出了一个题,同时邀请大家一起来作。
秋实大哥的题目要求你维护一个序列,支持两种操作:一种是修改某一个元素的值;一种是询问一段区间的和。
Input
第一行包含一个整数 n n,表示序列的长度。
接下来一行包含 n n个整数 ai ai,表示序列初始的元素。
接下来一行包含一个整数 m m,表示操作数。
接下来 m m行,每行是以下两种操作之一:
1 x v : 表示将第x个元素的值改为v 2 l r : 表示询问[l,r]这个区间的元素和
1≤n,m,v,ai≤100000 1≤n,m,v,ai≤100000, 1≤l≤r≤n 1≤l≤r≤n。
Output
对于每一个 2 2 l l r r操作,输出一个整数占一行,表示对应的答案。
Sample Input | Sample Output |
---|---|
3 1 2 3 3 2 1 2 1 1 5 2 1 2 | 3 7 |
ac代码:
/*
线段树模板题,基础题,一定要搞懂
*/
#include <cstdio>
#include <iostream>
using namespace std;
#define maxn 100005
#define ll long long
ll sum[maxn<<2];
void Build(int l, int r, int rt)//建树
{
if(l == r)
{
scanf("%lld", &sum[rt]);
return ;
}
int m = (l + r) >> 1;
Build(l, m, rt<<1);
Build(m+1, r, rt<<1|1);
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void update(int l, int r, int t, ll c, int rt)//更新
{
if(l == r)
{
sum[rt] = c;
return ;
}
int m = (l + r) >> 1;
if(t <= m) update(l, m, t, c, rt<<1);
else update(m+1, r, t, c, rt<<1|1);
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
ll query(int L, int R, int l, int r, int rt)//查询
{
if(l >= L && r <= R)
{
return sum[rt] ;
}
int m = (l + r) >> 1;
ll res = 0;
if(m >= L) res += query(L, R, l, m, rt<<1);
if(m < R) res += query(L, R, m+1, r, rt<<1|1);
return res;
}
int main()
{
int n, m, a, b;
ll c;
scanf("%d", &n);
Build(1, n, 1);
scanf("%d", &m);
while(m--)
{
scanf("%d%d%lld", &a, &b, &c);
if(a == 1){
update(1, n, b, c, 1);
}
else printf("%lld\n", query(b, c, 1, n, 1));
}
return 0;
}
题目链接: 点击打开链接http://acm.uestc.edu.cn/#/problem/show/1073