zoukankan      html  css  js  c++  java
  • 洛谷P2357 守墓人 题解 数列分块

    题目链接:https://www.luogu.com.cn/problem/P2357

    涉及操作:

    1. 区间更新;
    2. 单点更新(直接算到区间更新里面);
    3. 区间查询;
    4. 单点查询(直接算到区间查询里面)。

    解题思路:

    数列分块。

    \(tag[i]\) 表示第 \(i\) 个分块中每个数都增加的值;\(sum[i]\) 表示第 \(i\) 个分块中非整体增加的数值和。

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 200020;
    int n, m, blo, bl[maxn];
    long long a[maxn], sum[505], tag[505];
    
    void add(int l, int r, long long k) {
        for (int i = l; i <= min(r, bl[l]*blo); i ++)
            a[i] += k, sum[bl[i]] += k;
        if (bl[l] != bl[r]) {
            for (int i = (bl[r]-1)*blo+1; i <= r; i ++)
                a[i] += k, sum[bl[i]] += k;
        }
        for (int i = bl[l]+1; i < bl[r]; i ++)
            tag[i] += k;
    }
    
    long long query(int l, int r) {
        long long res = 0;
        for (int i = l; i <= min(r, bl[l]*blo); i ++)
            res += a[i] + tag[bl[i]];
        if (bl[l] != bl[r]) {
            for (int i = (bl[r]-1)*blo+1; i <= r; i ++)
                res += a[i] + tag[bl[i]];
        }
        for (int i = bl[l]+1; i < bl[r]; i ++)
            res += sum[i] + tag[i] * blo;
        return res;
    }
    
    int main() {
        ios::sync_with_stdio(0);
        cin >> n >> m;
        blo = sqrt(n);
        for (int i = 1; i <= n; i ++) {
            cin >> a[i];
            bl[i] = (i - 1) / blo + 1;
            sum[bl[i]] += a[i];
        }
        while (m --) {
            int op;
            cin >> op;
            if (op == 1) {
                int l, r; long long k;
                cin >> l >> r >> k;
                add(l, r, k);
            }
            else if (op == 2) {
                long long k;
                cin >> k;
                add(1, 1, k);
            }
            else if (op == 3) {
                long long k;
                cin >> k;
                add(1, 1, -k);
            }
            else if (op == 4) {
                int l, r;
                cin >> l >> r;
                cout << query(l, r) << endl;
            }
            else { // op == 5
                cout << query(1, 1) << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    价值观
    周记 改
    周记
    C语言问卷调查
    icon踩坑记录
    console.log(a)和console.log(window.a)的区别?
    记录一次微信二次分享的优化过程
    在jQuery中使用自定义属性
    10个JS技巧
    日常工作总结 2019/10/10
  • 原文地址:https://www.cnblogs.com/quanjun/p/15576704.html
Copyright © 2011-2022 走看看