首页 > 其他 > 详细

LOJ #6280. 数列分块入门 4

时间:2020-01-19 17:58:12      阅读:79      评论:0      收藏:0      [点我收藏+]

题目链接

思路&&代码

区间修改+区间查值

这个就是在数列分块入门\(1\)的基础上加了一个\(sum[i]\)

先分块,把这\(n\)个数分成\(\sqrt{n}\)个块,用\(add[i]\)表示这个块修改值的和(增量标记),用\(sum[i]\)表示这个块内数的和

如果第一题会了,这个也很容易明白,就不讲了\(qwq\)

时间复杂度\(O(n\sqrt{n})\)

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#define int long long
using namespace std;

const int A = 1e5 + 11;

inline int read() {
    char c = getchar(); int x = 0, f = 1;
    for ( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    return x * f;
}

int n, m, t;
int a[A], sum[A], add[A], L[A], R[A], pos[A];

void change(int l, int r, int c) {
    int p = pos[l], q = pos[r];
    if(p == q) {
        for(int i = l; i <= r; i++) a[i] += c;
        sum[p] += (r - l + 1) * c; return;
    }
    for(int i = p + 1; i < q; i++) add[i] += c;
    for(int i = l; i <= R[p]; i++) a[i] += c; sum[p] += (R[p] - l + 1) * c;
    for(int i = L[q]; i <= r; i++) a[i] += c; sum[q] += (r - L[q] + 1) * c;
}

int ask(int l, int r, int c) {
    int ans = 0, p = pos[l], q = pos[r];
    if(p == q) {
        for(int i = l; i <= r; i++) ans += a[i], ans %= (c + 1);
        ans += add[p] * (r - l + 1);
        return ans % (c + 1);
    }
    for(int i = p + 1; i < q; i++) ans += sum[i] + add[i] * (R[i] - L[i] + 1), ans %= (c + 1);
    for(int i = l; i <= R[p]; i++) ans += a[i], ans %= (c + 1); ans += add[p] * (R[p] - l + 1), ans %= (c + 1);
    for(int i = L[q]; i <= r; i++) ans += a[i], ans %= (c + 1); ans += add[q] * (r - L[q] + 1), ans %= (c + 1);
    return ans % (c + 1);
}

signed main() {
    n = read();
    for(int i = 1; i <= n; i++) a[i] = read();
    t = sqrt(n);
    for(int i = 1; i <= t; i++) {
        L[i] = (i - 1) * sqrt(n) + 1;
        R[i] = i * sqrt(n);
    }
    if(R[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n;
    for(int i = 1; i <= t; i++) {
        for(int j = L[i]; j <= R[i]; j++) {
            pos[j] = i;
            sum[i] += a[j];
        }
    }
    m = n;
    while(m--) {
        int opt, l, r, c;
        opt = read(), l = read(), r = read(), c = read();
        if(opt == 0) change(l, r, c);
        else cout << ask(l, r, c) << "\n";
    }
}

LOJ #6280. 数列分块入门 4

原文:https://www.cnblogs.com/loceaner/p/12210941.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!