贴一个被TLE的分块代码, 分块确实难调
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
const int NUMBER = 1e5 + 10, LEN = 400;
int number, op_number, len;
int id[NUMBER], _left[LEN], _right[LEN];
LL arr[NUMBER], add[LEN], mul[LEN], sum[LEN], mod;
//将当前区块中的懒标记进行下传
inline void push_down(int _index) {
if (mul[_index] == 1 && add[_index] == 0) return;
for (int i = _left[_index]; i <= _right[_index]; ++i) {
arr[i] = (arr[i] * mul[_index] + add[_index]) % mod;
}
add[_index] = 0;
mul[_index] = 1;
}
inline void change_mul(int left, int right, LL val) {
push_down(id[left]);
int temp = min(right, _right[id[left]]);
for (int i = left; i <= temp; ++i) {
sum[id[left]] += (val - 1) * arr[i] % mod;
arr[i] = arr[i] * val % mod;
}
if (id[left] != id[right]) {
push_down(id[right]);
for (int i = right; i >= _left[id[right]]; --i) {
sum[id[right]] += (val - 1) * arr[i] % mod;
arr[i] = arr[i] * val % mod;
}
}
for (int i = id[left] + 1; i <= id[right] - 1; ++i) {
mul[i] = mul[i] * val % mod;
add[i] = add[i] * val % mod;
sum[i] = sum[i] * val % mod;
}
}
inline void change_add(int left, int right, LL val) {
push_down(id[left]);
sum[id[left]] = (sum[id[left]] + (min(right, _right[id[left]]) - left + 1) * val) % mod;
int temp = min(right, _right[id[left]]);
for (int i = left; i <= temp; ++i) {
arr[i] = (arr[i] + val) % mod;
}
if (id[left] != id[right]) {
push_down(id[right]);
sum[id[right]] = (sum[id[right]] + ((right - _left[id[right]] + 1) * val)) % mod;
for (int i = right; i >= _left[id[right]]; --i) {
arr[i] = (arr[i] + val) % mod;
}
for (int i = id[left] + 1; i <= id[right] - 1; ++i) {
add[i] = (add[i] + val) % mod;
sum[i] = (sum[i] + len * val) % mod;
}
}
}
inline LL query(int left, int right) {
LL res = 0;
int temp = min(right, _right[id[left]]);
for (int i = left; i <= temp; ++i) {
res = (res + (arr[i] * mul[id[left]] + add[id[left]]) % mod) % mod;
}
if (id[left] != id[right]) {
for (int i = right; i >= _left[id[right]]; --i) {
res = (res + (arr[i] * mul[id[right]] + add[id[right]]) % mod) % mod;
}
for (int i = id[left] + 1; i <= id[right] - 1; ++i) {
res = (res + sum[i]) % mod;
}
}
return res % mod;
}
int main() {
scanf("%d%lld", &number, &mod);
len = sqrt(number);
for (int i = 1; i <= number; ++i) scanf("%lld", &arr[i]);
scanf("%d", &op_number);
// 初始化块的左边界和右边界
for (int i = 1; i <= number; ++i) id[i] = i / len;
for (int i = number; i >= 1; --i) _left[id[i]] = i;
for (int i = 1; i <= number; ++i) _right[id[i]] = i;
// 初始化块的值以及乘法因子
for (int i = 1; i <= number; ++i) {
sum[id[i]] = (sum[id[i]] + arr[i]) % mod;
}
for (int i = id[1]; i <= id[number]; ++i) mul[i] = 1;
int op, left, right, val;
while (op_number--) {
scanf("%d%d%d", &op, &left, &right);
if (op == 1) {
scanf("%d", &val);
change_mul(left, right, val);
}
else if (op == 2) {
scanf("%d", &val);
change_add(left, right, val);
}
else {
printf("%lld\n", query(left, right));
}
}
return 0;
}