数列分块入门 7

思路:先分块,对于更新操作,如果是左右两边的块,由于不一定是对块的全部数操作,所以要先对直接已经预先乘和加的更新,否则如果是中间块,直接更新块即可

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <vector>
#include <cmath>
#include <stack>
#include <random>
using namespace std;
#define io ios::sync_with_stdio(0),cin.tie(0)
#define ms(arr) memset(arr,0,sizeof(arr))
#define LD long double
#define LL long long
#define PI acos(-1.0)
#define INF 0x3f3f3f3f
#define inf 1<<30
#define  ull unsigned long long
const int Mod = 10007;
const int maxn = 1e6 + 5;
int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
int n, m, block;
int opt, l, r, c;
int a[maxn];
int belong[maxn];
int add[maxn];
int mul[maxn];
void rest(int x) {//对当前块依次更新
    for (int i = (belong[x] - 1) * block + 1; i <= min(belong[x] * block, n); i++) {
        a[i] = (mul[belong[i]] * a[i] + add[belong[i]]) % Mod;
    }
    mul[belong[x]] = 1;
    add[belong[x]] = 0;
}
void Add(int l, int r, int val) {
    rest(l);//先对l块更新再操作
    for (int i = l; i <= min(r, belong[l] * block); i++) {
        a[i] = (a[i]+val) % Mod;
    }
    if (belong[l] != belong[r]) {//不在同一块
        rest(r);//对r块进行更新
        for (int i = (belong[r] - 1) * block + 1; i <= min(r, belong[r] * block); i++) {//对最右边块操作
            a[i] = (a[i] + val) % Mod;
        }
        for (int i = belong[l] + 1; i <= belong[r] - 1; i++) {//中间块不必更新,直接操作即可
            add[i] = (add[i] + val) % Mod;
        }
    }
}
void Mul(int l, int r, int val) {
    rest(l);//先更新
    for (int i = l; i <= min(r, belong[l] * block); i++) {//对最左边块更新
        a[i] = (a[i] * val) % Mod;
    }
    if (belong[l] != belong[r]) {//不在同一块
        rest(r);//更新最右边块
        for (int i = (belong[r] - 1) * block + 1; i <= min(r, belong[r] * block); i++) {//操作
            a[i] = (a[i] * val) % Mod;
        }
        for (int i = belong[l] + 1; i <= belong[r] - 1; i++) {//对中间块操作
            add[i] = (add[i] * val) % Mod;//对中间块预先加的也要乘
            mul[i] = (mul[i] * val) % Mod;
        }
    }
}
int query(int x)
{
    int ans;
    ans = (a[x] * mul[belong[x]] + add[belong[x]]) % Mod;//询问时候返回
    return ans;
}
int main() {
    scanf("%d", &n);
    block = sqrt(n);
    m = n / block;
    if (n % block)
        m++;
    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        a[i] %= Mod;
        belong[i] = (i - 1) / block + 1;
        add[belong[i]] = 0;
        mul[belong[i]] = 1;
    }
    for (int i = 1; i <= n; i++) {
        scanf("%d%d%d%d", &opt, &l, &r, &c);
        if (opt == 0) {
            Add(l, r, c);
        }
        else if (opt == 1) {
            Mul(l, r, c);
        }
        else {
            cout << query(r) << endl;
        }
    }
}

 

posted @ 2021-03-29 20:32  夜灯长明  阅读(102)  评论(0编辑  收藏  举报