算法训练 操作格子
时间限制:1.0s 内存限制:256.0MB
问题描述
有n个格子,从左到右放成一排,编号为1-n。
共有m次操作,有3种操作类型:
1.修改一个格子的权值,
2.求连续一段格子权值和,
3.求连续一段格子的最大值。
对于每个2、3操作输出你所求出的结果。
输入格式
第一行2个整数n,m。
接下来一行n个整数表示n个格子的初始权值。
接下来m行,每行3个整数p,x,y,p表示操作类型,p=1时表示修改格子x的权值为y,p=2时表示求区间[x,y]内格子权值和,p=3时表示求区间[x,y]内格子最大的权值。
输出格式
有若干行,行数等于p=2或3的操作总数。
每行1个整数,对应了每个p=2或3操作的结果。
样例输入
4 3
1 2 3 4
2 1 3
1 4 3
3 1 4
1 2 3 4
2 1 3
1 4 3
3 1 4
样例输出
6
3
3
数据规模与约定
对于20%的数据n <= 100,m <= 200。
对于50%的数据n <= 5000,m <= 5000。
对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <cmath> #include <cstdlib> #include <algorithm> #include <queue> using namespace std; struct Line { int l, r; int sum, max; }; Line arr[300005]; void Build(int seat, int l, int r) { arr[seat].l = l; arr[seat].r = r; arr[seat].sum = 0; arr[seat].max = 0; if(l == r) return; Build(seat * 2, l, (l + r) / 2); Build(seat * 2 + 1, (l + r) / 2 + 1, r); } void Insert(int seat, int v, int num) { arr[seat].sum += num; if(arr[seat].max < num) arr[seat].max = num; if(arr[seat].l == arr[seat].r) return; if(v <= (arr[seat].l + arr[seat].r) / 2) Insert(seat * 2, v, num); else Insert(seat * 2 + 1, v, num); } void Change(int seat, int v, int num) { if(v == arr[seat].l && v == arr[seat].r) { arr[seat].sum = num; arr[seat].max = num; return; } int middle = (arr[seat].l + arr[seat].r) / 2; if(v <= middle) Change(seat * 2, v, num); else Change(seat * 2 + 1, v, num); arr[seat].sum = arr[seat * 2].sum + arr[seat * 2 + 1].sum; arr[seat].max = max(arr[seat * 2].max, arr[seat * 2 + 1].max); } int QuerySum(int seat, int l, int r) { if(l == arr[seat].l && r == arr[seat].r) return arr[seat].sum; int middle = (arr[seat].l + arr[seat].r) / 2; if(r <= middle) return QuerySum(seat * 2, l, r); else if(l > middle) return QuerySum(seat * 2 + 1, l, r); else return QuerySum(seat * 2, l, middle) + QuerySum(seat * 2 + 1, middle + 1, r); } int QueryMax(int seat, int l, int r) { if(l == arr[seat].l && r == arr[seat].r) return arr[seat].max; int middle = (arr[seat].l + arr[seat].r) / 2; if(r <= middle) return QueryMax(seat * 2, l, r); else if(l > middle) return QueryMax(seat * 2 + 1, l, r); else return max(QueryMax(seat * 2, l, middle), QueryMax(seat * 2 + 1, middle + 1, r)); } int main() { int n, m, temp, v, a, b; scanf("%d%d", &n, &m); Build(1, 1, n); for(int i = 1; i <= n; i++) { scanf("%d", &temp); Insert(1, i, temp); } while(m--) { scanf("%d%d%d", &v, &a, &b); if(v == 1) Change(1, a, b); else if(v == 2) printf("%d ", QuerySum(1, a, b)); else printf("%d ", QueryMax(1, a, b)); } return 0; }