P1438 无聊的数列

原题链接

  • 题意和思路:挺有意思的一道题,就是两个操作,第一个操作是在 (l)(r) 的区间上加上首项为 (k),公比为 (d) 的等差序列。第二个操作是询问第 (x) 个数是多少。其实就是区间修改 (+) 区间查询,操作一就是在 (l) 上加上 (k),然后在 (l + 1)(r) 上加上 (d),然后在 (r + 1) 上减去 ((r-(l + 1)-1) imes d + k)。需要注意的是,小心要是 (r + 1 > n) 会出现奇怪的错误,所以要细心边界。
  • 代码:
#include <cstdio>
#include <iostream>
using namespace std;
const ll inf = 0x3f3f3f3f;
const ll N = 1e5 + 9;
int a[N];
int sum[N];
struct segment_tree {
    struct node {
        int l, r, L, R, data, lazy;
    } tr[N << 2];
    inline void pushup(int p) {tr[p].data = tr[tr[p].l].data + tr[tr[p].r].data;}
    inline void pushdown(int p) {
        if (tr[p].lazy == 0) return;
        tr[tr[p].l].data += (tr[tr[p].l].R - tr[tr[p].l].L + 1) * tr[p].lazy;
        tr[tr[p].r].data += (tr[tr[p].r].R - tr[tr[p].r].L + 1) * tr[p].lazy;
        tr[tr[p].l].lazy += tr[p].lazy;
        tr[tr[p].r].lazy += tr[p].lazy;
        tr[p].lazy = 0;
        return;
    }
    inline void build(int l, int r, int p) {
        tr[p].L = l, tr[p].R = r;
        tr[p].l = p << 1;
        tr[p].r = p << 1 | 1;
        if (l == r) {
            tr[p].data = a[l];
            return;
        }
        int mid = l + r >> 1;
        build(l, mid, tr[p].l);
        build(mid + 1, r, tr[p].r);
        pushup(p);
    }
    inline void add(int l, int r, int num, int p) {
        if (tr[p].L >= l && tr[p].R <= r) {
            tr[p].data += num * (tr[p].R - tr[p].L + 1);
            tr[p].lazy += num;
            return;
        }
        pushdown(p);
        int mid = l + r >> 1;
        if (tr[tr[p].l].R >= l) add(l, r, num, tr[p].l);
        if (tr[tr[p].r].L <= r) add(l, r, num, tr[p].r);
        pushup(p);
    }
    inline int ask(int l, int r, int p) {
        if (tr[p].L >= l && tr[p].R <= r) {
            return tr[p].data;
        }
        pushdown(p);
        int ret = 0;
        if (tr[tr[p].l].R >= l) ret += ask(l, r, tr[p].l);
        if (tr[tr[p].r].L <= r) ret += ask(l, r, tr[p].r);
        return ret;
    }
} T;
signed main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i - 1] + a[i];
    T.build(1, n, 1);
    while (m--) {
        int op;
        scanf("%d", &op);
        if (op == 1) {
            int l, r, k, d;
            scanf("%d%d%d%d", &l, &r, &k, &d);
            T.add(l, l, k, 1);
            if (r != l) T.add(l + 1, r, d, 1);
            int sub = (r - (l + 1) + 1) * d + k;
            if (r + 1 <= n)
            T.add(r + 1, r + 1, -sub, 1);
        } else {
            int x;
            scanf("%d", &x);
            printf("%d
", T.ask(1, x, 1) - sum[x - 1]);
        }
    }
}
原文地址:https://www.cnblogs.com/Xiao-yan/p/14688361.html