题目链接:http://acm.uestc.edu.cn/#/problem/show/1073
“学习本无底,前进莫徬徨。” 秋实大哥对一旁玩手机的学弟说道。
秋实大哥是一个爱学习的人,今天他刚刚学习了线段树这个数据结构。
为了检验自己的掌握程度,秋实大哥给自己出了一个题,同时邀请大家一起来作。
秋实大哥的题目要求你维护一个序列,支持两种操作:一种是修改某一个元素的值;一种是询问一段区间的和。
Input
第一行包含一个整数n ,表示序列的长度。
接下来一行包含n 个整数a i ,表示序列初始的元素。
接下来一行包含一个整数m ,表示操作数。
接下来m 行,每行是以下两种操作之一:
1 x v : 表示将第x个元素的值改为v 2 l r : 表示询问[l,r]这个区间的元素和
1≤n,m,v,a i ≤100000 ,1≤l≤r≤n 。
Output
对于每一个2 2 l l r r 操作,输出一个整数占一行,表示对应的答案。
Sample input and output
3 1 2 3 3 2 1 2 1 1 5 2 1 2
3 7
题意:基本的线段树建树,更新,查找操作。
注意事项:更新是对单个叶子节点进行操作,而不是区间,如果建树的时候,递归建立所有的树会超时。
所以采取的方法是哪里的叶子节点出现了,才对其进行建立。
代码:
#include <stdio.h> #include <string.h> #include <algorithm> #define N 100007 using namespace std; long long sum[N * 10]; void build(int t, int L, int R, int val, int i) { if(t == L && L == R) { sum[i] = (long long)val; return ; } int mid = (L + R) >> 1; if (t <= mid) build(t, L, mid, val, i<<1); else if (t > mid) build(t, mid + 1, R, val, i<<1|1); sum[i] = sum[i<<1] + sum[i<<1|1]; } long long query(int l, int r, int L, int R, int i) { if (l == L && r == R) return sum[i]; int mid = (L + R) >> 1; if (r <= mid) return query(l, r, L, mid, i<<1); else if (l > mid) return query(l, r, mid + 1, R, i<<1|1); else { return query(l, mid, L, mid, i<<1) + query(mid + 1, r, mid + 1, R, i<<1|1); } sum[i] = sum[i<<1] + sum[i<<1|1]; } int main() { int n, m; while (scanf("%d", &n) != EOF) { int temp; for (int i = 0; i < n; i++) { scanf("%lld", &temp); build(i + 1, 1, n, temp, 1); } scanf("%d", &m); for (int i = 0; i < n; i++) { int order, a, b; scanf("%d%d%d", &order, &a, &b); if (order == 1) { build(a, 1, n, b, 1); } else { printf("%lld\n", query(a, b, 1, n, 1)); } } } return 0; }
时间: 2024-10-12 05:39:42