问题描述
有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 <stdio.h>
#define left (2 * i)
#define right (2 * i + 1)
#define mid ((a[i].l + a[i].r) / 2)
#define max(a, b) (a)>(b)?(a):(b)
struct node{
int l, r, sum, max;
}a[1000000];
void init(int x, int y, int i)
{
a[i].l = x;
a[i].r = y;
a[i].sum = 0;
a[i].max = 0;
if(x != y){
init(x, mid, left);
init(mid+1, y, right);
}
}
void input(int i, int x, int w)
{
if(x == a[i].l && x == a[i].r){
a[i].sum = w;
a[i].max = w;
}
else{
if(x > mid){
input(right, x, w);
}else{
input(left, x, w);
}
a[i].sum = a[left].sum + a[right].sum;
a[i].max = max(a[left].max, a[right].max);
}
}
int get_sum(int x, int y, int i)
{
if(a[i].l == x && a[i].r == y){
return a[i].sum;
}
if(x > mid){
return get_sum(x, y, right);
}
else if(y <= mid){
return get_sum(x, y, left);
}
else{
return get_sum(x, mid, left) + get_sum(mid+1, y, right);
}
}
int get_max(int x, int y, int i)
{
if(a[i].l == x && a[i].r == y){
return a[i].max;
}
if(x > mid){
return get_max(x, y, right);
}
else if(y <= mid){
return get_max(x, y, left);
}
else{
return max(get_max(x, mid, left), get_max(mid+1, y, right));
}
}
int main()
{
int i, n, m, w, p, x, y;
scanf("%d%d", &n, &m);
init(1, n, 1);
for(i = 1; i <= n; i ++){
scanf("%d", &w);
input(1, i, w);
}
for(i = 0; i < m; i ++){
scanf("%d%d%d", &p, &x, &y);
switch(p){
case 1:
input(1, x, y);
break;
case 2:
printf("%d\n", get_sum(x, y, 1));
break;
case 3:
printf("%d\n", get_max(x, y, 1));
break;
}
}
return 0;
}