算法训练 操作格子

问题描述

有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
样例输出
6
3
数据规模与约定

对于20%的数据n <= 100,m <= 200。

对于50%的数据n <= 5000,m <= 5000。

对于100%的数据1 <= n <= 100000,m <= 100000,0 <= 格子权值 <= 10000。

 
练习了一下线段树,习惯了敲模板,蓝桥杯却不能看模板,赶脚好痛苦。。。
#include <cstdio>
#include <algorithm>
#define N 1000005
#define ll long long
using namespace std;
ll sum[N] = {0};
ll Max[N] = {0};
void PushUp(int rt)
{
    Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]);
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
}

void Build(int rt, int l, int r)
{
    if(l == r) {
            scanf("%I64d", &sum[rt]);
            Max[rt] = sum[rt];
    }
    else {
        int m = (l + r) >> 1;
        Build(rt << 1, l, m);
        Build(rt << 1 | 1, m + 1, r);
        PushUp(rt);
    }
}

void UpDate(int p, int val, int l, int r, int rt)
{
    if(l == r) { sum[rt] = val; Max[rt] = val; }
    else {
        int m = (l + r) >> 1;
        if(p <= m) UpDate(p, val, l, m, rt << 1);
        else       UpDate(p, val, m + 1, r, rt << 1 | 1);
        PushUp(rt);
    }
}

ll Query_max(int L, int R, int l, int r, int rt)
{
    if(L <= l && R >= r) return Max[rt];
    else {
        int m = (l + r) >> 1;
        ll ans = 0;
        if(L <= m) ans = max(Query_max(L, R, l, m, rt << 1), ans);
        if(R > m)  ans = max(Query_max(L, R, m + 1 , r, rt << 1 | 1), ans);
        return ans;
    }
}

ll Query_sum(int L, int R, int l, int r, int rt)
{
    if(L <= l && R >= r) return sum[rt];
    else {
        int m = (l + r) >> 1;
        ll ans = 0;
        if(L <= m) ans += Query_sum(L, R, l, m, rt << 1);
        if(m < R)  ans += Query_sum(L, R, m + 1 , r, rt << 1 | 1);
        return ans;
    }
}

int main()
{
    int n, q;
    scanf("%d%d", &n, &q);
    Build(1, 1, n);
    for(int i = 0; i < q; i++)
    {
        int op, a, b;
        scanf("%d%d%d", &op, &a, &b);
        if(op == 1) UpDate(a, b, 1, n, 1);
        else if(op == 2) printf("%I64d
", Query_sum(a, b, 1, n, 1));
        else             printf("%I64d
", Query_max(a, b, 1, n, 1));
    }
    return 0;
}
View Code
 
原文地址:https://www.cnblogs.com/sunus/p/4533565.html