luogu P5309 [Ynoi2011] 初始化

https://www.luogu.com.cn/problem/P5309

分块+根号分治

考虑周期长度x

  • 如果 x > = n x >= \sqrt{n} x>=n 就暴力改
  • 否则每一个周期单独考虑,然后把结果加起来
    对于一个周期 x x x,它对询问 [ l , r ] [l,r] [l,r]对贡献一定是完整的几块再加上左右两边的散块,左右两边的散块可以用x对于每个y的前缀和和后缀和来快速计算,如果没有完整的一块就用前缀和减一下

总的来说就是分两部分计算,算本来的和还有每个周期的贡献和
code:

#include<bits/stdc++.h>
#define N 200050
#define mod 1000000007
using namespace std;
void add(int &x, int y) { x += y;
    if(x >= mod) x -= mod;
}
void sub(int &x, int y) { x -= y;
    if(x < 0) x += mod;
}
int a[N], bel[N], sum[N], pre[505][505], suf[505][505], n, m, blo;
void update(int x, int y, int z) {
    if(x >= blo) {
        for(int i = y; i <= n; i += x) {
            add(a[i], z), add(sum[bel[i]], z);
        }
        return ;
    }
    for(int i = y; i <= x; i ++) add(pre[x][i], z);
    for(int i = 1; i <= y; i ++) add(suf[x][i], z);
}
int getsum(int l, int r) {
    int ans = 0;
    if(bel[l] == bel[r]) {
        for(int i = l; i <= r; i ++) add(ans, a[i]);
        return ans;
    }
    for(int i = bel[l] + 1; i <= bel[r] - 1; i ++) add(ans, sum[i]);
    for(int i = l; i <= bel[l] * blo; i ++) add(ans, a[i]);
    for(int i = (bel[r] - 1) * blo + 1; i <= r; i ++) add(ans, a[i]);
    return ans % mod;
}
int query(int l, int r) {
    int ans = getsum(l, r);
    for(int x = 1; x < blo; x ++) {
        int L = (l - 1) / x + 1, R = (r - 1) / x + 1;
        if(L == R) sub(ans, pre[x][(l - 1) % x]), add(ans, pre[x][(r - 1) % x + 1]);
        else ans = (ans + 1ll * (R - L - 1) * pre[x][x] + pre[x][(r - 1) % x + 1] + suf[x][(l - 1) % x + 1]) % mod;
    }
    return ans;
}
int main() {
    scanf("%d%d", &n, &m); blo = sqrt(n) + 1;
    for(int i = 1; i <= n; i ++) scanf("%d", &a[i]), bel[i] = (i - 1) / blo + 1, a[i] %= mod, add(sum[bel[i]], a[i]);
    
    while(m --) {
        int o, x, y, z;
        scanf("%d", &o);
        if(o == 1) {
            scanf("%d%d%d", &x, &y, &z);
            update(x, y, z % mod);
        } else {
            scanf("%d%d", &x, &y);
            printf("%d\n", query(x, y));
        }
    }
    return 0;
}
posted @ 2021-08-30 20:20  lahlah  阅读(30)  评论(0编辑  收藏  举报