lss233 3 min read

这题也是线段树

单组数据,第一行一个正整数n。(1<=n<=10^5)

第二行n个数 a1,a2...an。(0<= |a[i]| <=10^7)

第三行一个整数m,表示m个操作。 (1<=m<=10^5)

接下来m行,每行第一个数表示操作类型,其余数表示操作对应的参数,对应题面。 (1<=l<=r<=n,0<=|v|<=10^7)

输入

单组数据,第一行一个正整数n。(1<=n<=10^5)

第二行n个数 a1,a2...an。(0<= |a[i]| <=10^7)

第三行一个整数m,表示m个操作。 (1<=m<=10^5)

接下来m行,每行第一个数表示操作类型,其余数表示操作对应的参数,对应题面。 (1<=l<=r<=n,0<=|v|<=10^7)

输出

对于每一个3操作,输出一行三个整数,表示区间和,最大值,最小值。

样例输入

5
1 2 3 4 5
7
1 1 1 -2
3 1 2
1 3 5 1
3 1 5
3 3 3
2 3 3 3
3 3 3

样例输出

1 2 -1
16 6 -1
4 4 4
3 3 3

题解

这题应该算是线段树的模板题了吧。最大值、最小值、求和、区间改值都有了。
所以特此记录一下。

代码

#include <bits/stdc++.h>
#define L(x) (x << 1)
#define R(x) (x << 1 | 1)
typedef long long ll;
const int MAX_N = 2e5 + 10;
struct leaf
{
    ll max, min, sum;
    leaf()
    {
        max = 0, min = 0, sum = 0;
    }
} tree[MAX_N * 4];
ll data[MAX_N], lazy_add[MAX_N * 4], lazy_set[MAX_N * 4];
bool is_lazy_set[MAX_N * 4];
void push_up(int k)
{
    tree[k].sum = tree[L(k)].sum + tree[R(k)].sum;
    tree[k].max = std ::max(tree[L(k)].max, tree[R(k)].max);
    tree[k].min = std ::min(tree[L(k)].min, tree[R(k)].min);
}
void push_down(int k, int a, int b)
{
    int m = (a + b) >> 1;
    if(is_lazy_set[k]) {
        lazy_add[L(k)] = lazy_add[R(k)] = 0;
        lazy_set[L(k)] = lazy_set[R(k)] = lazy_set[k];
        is_lazy_set[L(k)] = is_lazy_set[R(k)] = is_lazy_set[k];
        tree[L(k)].sum = (m - a + 1) * lazy_set[k];
        tree[L(k)].max = lazy_set[k];
        tree[L(k)].min = lazy_set[k];

        tree[R(k)].sum = (b - m) * lazy_set[k];
        tree[R(k)].max = lazy_set[k];
        tree[R(k)].min = lazy_set[k];
        is_lazy_set[k] = false;
    }
    if(lazy_add[k]) {
        lazy_add[L(k)] += lazy_add[k];
        lazy_add[R(k)] += lazy_add[k];
        tree[L(k)].sum += (m - a + 1) * lazy_add[k];
        tree[L(k)].max += lazy_add[k];
        tree[L(k)].min += lazy_add[k];

        tree[R(k)].sum += (b - m) * lazy_add[k];
        tree[R(k)].max += lazy_add[k];
        tree[R(k)].min += lazy_add[k];
        lazy_add[k] = 0;
    }
}
void build(int k, int l, int r)
{
    if (l == r)
    {
        tree[k].max = tree[k].min = tree[k].sum = data[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(L(k), l, mid);
    build(R(k), mid + 1, r);
    push_up(k);
}
void update(int k, int a, int b, int l, int r, int op, ll val)
{
    if (a <= l && r <= b)
    {
        if (op == 1) // add
        {
            tree[k].max += val;
            tree[k].min += val;
            tree[k].sum += val * (r - l + 1);
            lazy_add[k] += val;
        }
        else if (op == 2) // set
        {
            tree[k].max = val;
            tree[k].min = val;
            tree[k].sum = val * (r - l + 1);
            lazy_set[k] = val;
            lazy_add[k] = 0;
            is_lazy_set[k] = true;
        }
        return;
    }
    int mid = (l + r) >> 1;
    push_down(k, l, r);
    if (a <= mid)
    {
        update(L(k), a, b, l, mid, op, val);
    }
    if (mid < b)
    {
        update(R(k), a, b, mid + 1, r, op, val);
    }
    push_up(k);
}
leaf query(int k, int a, int b, int l, int r)
{
    if (a <= l && r <= b)
    {
        return tree[k];
    }
    push_down(k, l, r);
    int mid = (l + r) >> 1;
    leaf ans;
    if (a <= mid && mid < b)
    {
        leaf resA = query(L(k), a, b, l, mid);
        leaf resB = query(R(k), a, b, mid + 1, r);
        ans.max = std ::max(resA.max, resB.max);
        ans.min = std ::min(resA.min, resB.min);
        ans.sum = resA.sum + resB.sum;
        return ans;
    }
    if (a <= mid)
    {
        return query(L(k), a, b, l, mid);
    }
    if (mid < b)
    {
        return query(R(k), a, b, mid + 1, r);
    }
    return ans;
}
int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%lld", &data[i]);
    }
    build(1, 1, n);
    int m;
    scanf("%d", &m);
    while (m--)
    {
        int op, l, r;
        scanf("%d%d%d", &op, &l, &r);
        if (op < 3)
        {
            ll val;
            scanf("%lld", &val);
            update(1, l, r, 1, n, op, val);
        }
        else
        {
            leaf res = query(1, l, r, 1, n);
            printf("%lld %lld %lld\n", res.sum, res.max, res.min);
        }
    }
}