每日一题第三期3月2日:区区区间


题目链接:https://ac.nowcoder.com/acm/problem/200195

描述

给你一个长度为n的数组,进行m次操作。1 l r k代表把闭区间l~r中的数替换为以k为首项,公差为1的等差数列,即a[l]=k,a[l+1]=k+1...。2 l r则代表查询闭区间l~r的和。题目很明确是用线段树来写,维护一个带有懒惰标记的线段树即可,参考朝阳学长的做法https://blog.nowcoder.net/n/84adee5178c648a782c7a07ac4a85250
每次 查找/修改 遍历结点时将懒惰标记分成两块下推首项即可,每个结点的权值代表等差数列的和

#include <bits/stdc++.h>

#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define mem(a, b) memset(a, b, sizeof(a))
#define ios ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define endl "\n"
#define int long long
const long long N = 1e6 + 7;
const double eps = 1e-6;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long mod = 1e9 + 7;
const int dir[][2] = {{0, 1}, {1, 0},  {0, -1}, {-1, 0},
                      {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const ll inf_ll = 0x3f3f3f3f3f3f3f3f;
int a[N];
int tree[N];
int tanlan[N];
int l, r;
int num;
int ans;
void buildtree(int node, int L, int R) {
    if (L == R) {
        tree[node] = a[L];
        return;
    }
    int mid = (L + R) >> 1;
    int l_node = node * 2;
    int r_node = node * 2 + 1;
    buildtree(l_node, L, mid);
    buildtree(r_node, mid + 1, R);
    tree[node] = tree[l_node] + tree[r_node];
}
int jisuan(int a, int n) { return (a + a + n - 1) * n / 2; }
void up(int node, int L, int R) {
    int mid = (R + L) >> 1;
    if (tanlan[node]) {
        int l_node = node * 2;
        int r_node = node * 2 + 1;
        tanlan[l_node] = tanlan[node];
        tanlan[r_node] = tanlan[node] + (mid - L + 1);
        tree[l_node] = jisuan(tanlan[l_node], mid - L + 1);
        tree[r_node] = jisuan(tanlan[r_node], R - mid);
        tanlan[node] = 0;
    }
}
void add(int node, int L, int R) {
    if (L >= l && R <= r) {
        tanlan[node] = num + L - l;
        tree[node] = jisuan(tanlan[node], R - L + 1);
        return;
    }
    int mid = (R + L) >> 1;
    int l_node = node * 2;
    int r_node = node * 2 + 1;
    up(node, L, R);
    if (mid >= l) add(l_node, L, mid);
    if (mid < r) add(r_node, mid + 1, R);
    tree[node] = tree[l_node] + tree[r_node];
}
int chaxun(int node, int L, int R) {
    if (L >= l && R <= r) return tree[node];
    up(node, L, R);
    int res = 0;
    int mid = (L + R) >> 1;
    int l_node = node * 2;
    int r_node = node * 2 + 1;
    if (l <= mid) res += chaxun(l_node, L, mid);
    if (r > mid) res += chaxun(r_node, mid + 1, R);
    return res;
}
signed main() {
    //ios;
    int n, k;
    cin >> n >> k;
    mem(tanlan, 0);
    mem(tree, 0);
    mem(a, 0);
    for (int i = 1; i <= n; i++) cin >> a[i];
    buildtree(1, 1, n);
    while (k--) {
        int op;
        cin >> op;
        cin >> l >> r;
        if (op == 1) {
            cin >> num;
            add(1, 1, n);
        } else {
            int ans = chaxun(1, 1, n);
            cout << ans << endl;
        }
    }
}