Luogu P1438 無聊的數列

# 解題思路

這題仍是有些噁心的,稍不注意就會 RE 或者是 WA。node

咱們先來看看題目中給出的要求:給定等差數列的公差和首項,在給定一個區間,給這個區間加上這個等差數列(逐項)。ios

emmmm,考慮一下給一個區間加了一個等差序列以後與原序列相比,有哪些改變,既然是加的等差數列,那每兩相鄰個數之間的差的變化是同樣的,爲題目中給出的公差。數組

那麼也就能夠想到用差分數組來作這道題。將原序列的變化搬到差分數組上以後,會發生以下的變化:ui

  • 差分數組的第一個數確定要加上 K。
  • 差分數組的 $(L,R]$ 這個區間內,每項都要加上 D。
  • 差分數組的第 $R+1$ 項要減去 $K+D\times (R-L)$

值得注意的是,在發生後兩種變化時要判斷區間的類型,若是這個區間的右端點是 $n$,那麼咱們就不進行第三個變化,若是這個區間的左右端點相等,就不進行第二個變化。spa

那從上面來看的話,這個題就是用線段樹維護差分數組,支持區間求和和區間加法。code

我寫線段樹的時候寫的懶標記在詢問時忘記下傳了,233,果真仍是我太菜。blog

 

# 附上代碼

給你們看看我奇醜無比自帶超大常數的傻逼線段樹get

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 1e5+3;
struct node {int l, r, sum, f;} tree[maxn << 2];
int n, m, a[maxn], d[maxn], tot = 0;
struct Segment {
    #define Lson (k << 1)
    #define Rson ((k << 1) | 1)
    void read(int &x) {
        x = 0; int f = 1; char c = getchar();
        while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
        while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
        x *= f;
    }
    void build(int k, int ll, int rr) {
        tree[k].l = ll, tree[k].r = rr;
        if(tree[k].l == tree[k].r) {
            tree[k].sum = 0;
            return ;
        }
        int mid = (tree[k].l + tree[k].r) >> 1;
        build(Lson, tree[k].l, mid);
        build(Rson, mid+1, tree[k].r);
        tree[k].sum = tree[Lson].sum + tree[Rson].sum;
    }
    void pushdown(int k) {
        tree[Lson].sum += tree[k].f * (tree[Lson].r - tree[Lson].l + 1);
        tree[Rson].sum += tree[k].f * (tree[Rson].r - tree[Rson].l + 1);
        tree[Lson].f += tree[k].f, tree[Rson].f += tree[k].f;
        tree[k].f = 0;
    }
    void update(int k, int L, int R, int num) {
        if(tree[k].l >= L && tree[k].r <= R) {
            tree[k].sum += (tree[k].r - tree[k].l + 1) * num;
            tree[k].f += num;
            return ;
        }
        if(tree[k].f) pushdown(k);
        int mid = (tree[k].l + tree[k].r) >> 1;
        if(L <= mid) update(Lson, L, R, num);
        if(R > mid) update(Rson, L, R, num);
        tree[k].sum = tree[Lson].sum + tree[Rson].sum;
    }
    int query(int k, int L, int R) {
        int ans = 0;
        if(tree[k].l >= L && tree[k].r <= R)
            return tree[k].sum;
        if(tree[k].f) pushdown(k);
        int mid = (tree[k].l + tree[k].r) >> 1;
        if(L <= mid) ans += query(Lson, L, R);
        if(R > mid) ans += query(Rson, L, R);
        return ans;
    }
    void init() {
        read(n), read(m);
        for(int i=1; i<=n; i++)
            read(a[i]);
    }
    void Query() {
        int opt, l, r, k, D;
        for(int i=1; i<=m; i++) {
            read(opt), read(l);
            if(opt == 1) {
                read(r), read(k), read(D);
                update(1, l, l, k);
                if(r != n) update(1, r+1, r+1, -(k+(r-l)*D));
                if(r > l) update(1, l+1, r, D);
            }
            else {
                printf("%d\n", a[l] + query(1, 1, l));
            }
        }
    }
    Segment () {
        init(), build(1, 1, n);
        Query();
    }
}T;
int main() {}
相關文章
相關標籤/搜索