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

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

    设计操作:

    1. 区间加法
    2. 区间乘法
    3. 单点查询

    解题思路:

    (X_i) 维护第 (i) 个分块当前乘的数,用 (Y_i) 维护第 (i) 个分块当前加的数。

    若当前乘了 (X_i),加了 (Y_i),则加了 (c) 之后 (Rightarrow) 乘的数不变,加的数变成了 (Y_i + c)

    若当前乘了 (X_i),加了 (Y_i),则乘了 (c) 之后 (Rightarrow) 乘的数变成了 (X_i imes c),加的数变成了 (Y_i imes c)

    而如果加或乘的区间不完全包含,则更新所有 (a_i),同时还原对应的分段 (p)(X_p = 1, Y_p = 0)(因为乘法的基数为 (1))。

    示例程序:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    const long long MOD = 10007;
    int n, blo, bl[maxn];
    long long a[maxn], X[505], Y[505];
    
    
    // 将第p个分块的修改还原到分块中的每个元素
    void recover(int p) {
        for (int i = (p-1)*blo+1; i <= min(p*blo,n); i ++) {
            a[i] = (a[i] * X[p] % MOD + Y[p]) % MOD;
        }
        X[p] = 1;
        Y[p] = 0;
    }
    
    void add(int l, int r, int c) {
        recover(bl[l]);
        for (int i = l; i <= min(bl[l]*blo, r); i ++)
            a[i] = (a[i] + c) % MOD;
        if (bl[l] != bl[r]) {
            recover(bl[r]);
            for (int i = (bl[r]-1)*blo+1; i <= r; i ++)
                a[i] = (a[i] + c) % MOD;
        }
        for (int i = bl[l]+1; i < bl[r]; i ++) {
            Y[i] = (Y[i] + c) % MOD;
        }
    }
    
    void multi(int l, int r, int c) {
        recover(bl[l]);
        for (int i = l; i <= min(bl[l]*blo, r); i ++)
            a[i] = (a[i] * c) % MOD;
        if (bl[l] != bl[r]) {
            recover(bl[r]);
            for (int i = (bl[r]-1)*blo+1; i <= r; i ++)
                a[i] = (a[i] * c) % MOD;
        }
        for (int i = bl[l]+1; i < bl[r]; i ++) {
            X[i] = X[i] * c % MOD;
            Y[i] = Y[i] * c % MOD;
        }
    }
    
    int query(int p) {
        // 这样查询是根号n的
        // recover(bl[p]);
        // return a[p];
        // 这样查询是O(1)的
        return (a[p] * X[bl[p]] + Y[bl[p]]) % MOD;
    }
    
    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;
        }
        for (int i = 1; i <= bl[n]; i ++) X[i] = 1; // 乘法的基数是1
        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 if (op == 1) {
                multi(l, r, c);
            }
            else {
                cout << query(r) << endl;
            }
        }
        return 0;
    }
    
  • 相关阅读:
    Java条件语句之多重 if
    Java条件语句之 if...else
    equals和==的区别
    Java条件语句之 if
    Java中运算符的优先级
    Java中的条件运算符
    tp 推送微信的模板消息
    thinkphp 上传多张图片
    图片服务器和WEB应用服务器相分离的简单方案
    PHP无限级分类实现(递归+非递归)
  • 原文地址:https://www.cnblogs.com/quanjun/p/15526498.html
Copyright © 2011-2022 走看看