操作格子
问题描述
有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。
题意很明确,更新点,求区间和and区间最大值,用线段树很好就求出来。
注意:线段树的大小应该是maxn * 4;如果开小就会提示运行超时。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 100010;
int n, m;
struct node{
int gl, gr, gsum, gmax;
};
node a[maxn * 4];
void init(int l, int r, int num)
{
a[num].gl = l;
a[num].gr = r;
a[num].gmax = 0;
a[num].gsum = 0;
if(l >= r)
return;
int mid = (l + r) >> 1;
init(l, mid, num << 1);
init(mid + 1, r, num << 1 | 1);
}
void insert(int num, int i, int x)
{
if(i < a[num].gl || i > a[num].gr)
return;
if(a[num].gl == a[num].gr)
{
if(i == a[num].gl)
{
a[num].gmax = x;
a[num].gsum = x;
}
return;
}
int mid = (a[num].gl + a[num].gr) >> 1;
if(i <= mid)
insert(num << 1, i, x);
else
insert(num << 1 | 1, i, x);
a[num].gmax = max(a[num << 1].gmax, a[num <<1 | 1].gmax);
a[num].gsum = a[num << 1].gsum +a[num << 1 | 1].gsum;
}
int getsum(int num, int l, int r)
{
if(l <= a[num].gl && r >= a[num].gr)
return a[num].gsum;
if(l > a[num].gr || r < a[num].gl)
return 0;
int mid = (a[num].gl + a[num].gr) >> 1;
if(l > mid)
return getsum(num << 1 | 1, l, r);
else if(r <= mid)
return getsum(num << 1, l, r);
else
return getsum(num << 1, l, mid) + getsum(num << 1 | 1, mid + 1, r);
}
int getmax(int num, int l, int r)
{
if(l == a[num].gl && r == a[num].gr)
return a[num].gmax;
if(l > a[num].gr || r < a[num].gl)
return 0;
int mid = (a[num].gl + a[num].gr) >> 1;
if(l > mid)
return getmax(num << 1 | 1, l, r);
else if(r <= mid)
return getmax(num << 1, l, r);
else
return max(getmax(num << 1, l, mid) , getmax(num << 1 | 1, mid + 1, r));
}
int main()
{
int cas, x, y;
scanf("%d%d", &n, &m);
init(1, n, 1);
for(int i = 1; i <= n; i++)
{
scanf("%d", &x);
insert(1, i, x);
}
for(int i = 0; i < m; i++)
{
scanf("%d%d%d", &cas, &x, &y);
if(cas == 1)
insert(1, x, y);
else if(cas == 2)
printf("%d\n", getsum(1, x, y));
else
printf("%d\n", getmax(1, x, y));
}
return 0;
}