zoukankan      html  css  js  c++  java
  • LOJ6280. 数列分块入门 4 题解

    题目链接:https://loj.ac/p/6280

    涉及操作:

    1. 区间加法;
    2. 区间求和。

    解题思路:

    数列分块。

    需要:

    • (sum_i) 表示第 (i) 个分块单独累加的数值和;
    • (tag_i) 表示第 (i) 个分块整体累加的数值和(就是分块 (i) 内的每个数都会增加 (tag_i))。

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 50050;
    int n, blo, bl[maxn];
    long long a[maxn], sum[505], tag[505];
    
    /**
    tag[i]记录第i个分块的数值和
    sum[i]第i个块所有单独增加的元素和
    */
    
    void add(int l, int r, long long val) {
        for (int i = l; i <= min(bl[l]*blo, r); i ++)
            a[i] += val, sum[bl[i]] += val;
        if (bl[l] != bl[r])
            for (int i = (bl[r]-1)*blo+1; i <= r; i ++)
                a[i] += val, sum[bl[i]] += val;
        for (int i = bl[l]+1; i < bl[r]; i ++)
            tag[i] += val;
    }
    
    long long query(int l, int r, long long M) {
        long long ans = 0;
        for (int i = l; i <= min(bl[l]*blo, r); i ++)
            ans += a[i] + tag[bl[i]];
        if (bl[l] != bl[r])
            for (int i = (bl[r]-1)*blo+1; i <= r; i ++)
                ans += a[i] + tag[bl[i]];
        for (int i = bl[l]+1; i < bl[r]; i ++)
            ans += sum[i] + tag[i] * blo;
        return (ans % M + M) % M;
    }
    
    int main() {
        ios::sync_with_stdio(0);
        cin >> n;
        blo = sqrt(n);
        for (int i = 1; i <= n; i ++) {
            cin >> a[i];
            bl[i] = (i - 1) / blo + 1;
            sum[bl[i]] += a[i];
        }
        for (int i = 0; i < n; i ++) {
            int op, l, r, c;
            cin >> op >> l >> r >> c;
            if (op == 0) add(l, r, c);
            else cout << query(l, r, c+1) << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    vs2005 enable your debug
    暑假的安排
    session
    我所看过的电影——不断更新中……
    symbian
    CUDA学习。。。visual assist 扩展
    MySQL密码修改
    fcitx in Fedora
    LDAP身份验证
    mysql自增auto_increment删除记录
  • 原文地址:https://www.cnblogs.com/quanjun/p/15525491.html
Copyright © 2011-2022 走看看