#include <iostream>
#include <vector>
#include <queue>
using namespace std;
constexpr long long MAXN = 400000;
class opera {
public:
short operation;// + is 1,* is 2
long long value;
opera(void) { ; };
opera(short O1, long long O2) { operation = O1; value = O2; };
};
class lineTree {
public:
long long a[MAXN + 1];
long long d[MAXN + 1];//真值
queue<opera> b[MAXN + 1];//偷懒标记
inline long long ls(long long n) {
return (n << 1);
}
inline long long rs(long long n) {
return ((n << 1) | 1);
}
void build(long long l, long long r, long long p) {//左区间,右区间,当前节点编号
if (l == r) {
d[p] = a[l];
return;
}
long long mid = (l + r) >> 1;
build(l, mid, ls(p));
build(mid + 1, r, rs(p));
d[p] = d[ls(p)] + d[rs(p)];
}
//添加一个操作,并简化
void A_mark(long long pos, long long _val, int op, long long len) {
if (len == 0)return;
if (!b[pos].empty() && b[pos].back().operation == op) {
if (op == 1) {
b[pos].back().value += _val;
d[pos] += (_val) * (len);
}
else {
b[pos].back().value *= _val;
d[pos] *= _val;
}
}
else {
b[pos].push(opera(op, _val));
if (op == 1)d[pos] += (_val) * (len);
else d[pos] *= _val;
}
}
//将当前累积的懒惰操作传递给儿子
void B_mark(long long p, long long l, long long r) {
long long m = (l + r) / 2;
opera t;
while (!b[p].empty()) {
t = b[p].front();
b[p].pop();
A_mark(ls(p), t.value, t.operation, m - l + 1);
A_mark(rs(p), t.value, t.operation, r - m);
}
}
//传入左区间,右区间,值,左管辖,右管辖,操作符
void update(long long l, long long r, long long c, long long s, long long t, long long p, int op) {
if (l <= s && t <= r) {
A_mark(p, c, op, t - s + 1);
return;
}
long long m = (s + t) >> 1;
B_mark(p, s, t);
if (l <= m) update(l, r, c, s, m, ls(p), op);
if (r > m) update(l, r, c, m + 1, t, rs(p), op);
d[p] = d[ls(p)] + d[rs(p)];
}
long long sum(long long l, long long r, long long s, long long t, long long p) {
if (l <= s && t <= r)return d[p];
long long m = (s + t) >> 1;
B_mark(p, s, t);
long long ret = 0;
if (l <= m) ret += sum(l, r, s, m, ls(p));
if (m < r) ret += sum(l, r, m + 1, t, rs(p));
return ret;
}
void operator()(long long n) {//上界
build(1, n, 1);
}
lineTree() { ; };
};
lineTree t;
int main() {
// freopen("in", "r", stdin);
long long n, q, m;
cin >> n >> m >> q;
for (long long i = 1; i <= n; i++) {
cin >> t.a[i];
}
t(n);
long long opt, a, b, c;
for (long long i = 1; i <= m; i++) {
cin >> opt;
if (opt == 1 || opt == 2) {
cin >> a >> b >> c;
t.update(a, b, c, 1, n, 1, opt);
}
else {
cin >> a >> b;
cout << t.sum(a, b, 1, n, 1) << endl;
}
}
system("pause");
return 0;
}
没错又来拉屎了
拉了坨大的
又臭又长
大概思路就是沿用懒惰操作的思想,把操作都暂时存起来,然后update到该节点时,将懒惰操作传代给儿子,然后按顺序更新儿子的值
sum和build是可信的
暂时没有写取模 ,毕竟样例都没过
不能确定逻辑有没有问题,尤其是A_mark和B_mark,都是进行了重大改动,还有update
update用于更新,sum用于求和
脑容量有限,不能进行深度思考,我尽力了