做法,线段树
线段树维护一个等差序列。
懒标记:记录当前的k值,记录k值所在位置
#include <iostream>
#include <cstdio>
using namespace std;
#define int long long
const int N = 200010;
struct Node {
int l, r, sum, add, t;
}tr[N * 4];
int n, m;
int w[N];
void pushup(Node &c, Node &a, Node &b) {
c.sum = a.sum + b.sum;
}
void pushup(int u) {
pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}
//u表示修改的线段树节点编号,l表示k所在的位置
void add(int u, int k, int l) {
int len = tr[u].r - tr[u].l + 1;
tr[u].sum = len * (tr[u].l + (k - l) + tr[u].r + (k - l)) / 2;
tr[u].add = k, tr[u].t = l;
}
void pushdown(int u) {
if (!tr[u].add) return;
add(u << 1, tr[u].add, tr[u].t);
add(u << 1 | 1, tr[u].add, tr[u].t);
tr[u].add = 0; tr[u].t = 0;
}
void build(int u, int l, int r) {
if (l == r) {
tr[u] = {l, l, w[l], 0};
return;
}
tr[u] = {l, r};
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
void change(int u, int l, int r, int k) {
if (l <= tr[u].l && tr[u].r <= r) {
add(u, k, l);
return;
}
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
if (l <= mid) change(u << 1, l, r, k);
if (r > mid) change( u << 1 | 1, l, r, k);
pushup(u);
}
int query(int u, int l, int r) {
if (l <= tr[u].l && tr[u].r <= r) return tr[u].sum;
pushdown(u);
int mid = tr[u].l + tr[u].r >> 1;
int sum = 0;
if (l <= mid) sum += query(u << 1, l, r);
if (r > mid) sum += query(u << 1 | 1, l, r);
return sum;
}
signed main() {
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n; i ++ ) scanf("%lld", &w[i]);
build(1, 1, n);
while (m -- ) {
int op, l, r, k;
scanf("%lld%lld%lld", &op, &l, &r);
if (op == 1) {
scanf("%lld", &k);
change(1, l, r, k);
}
else {
printf("%lld\n", query(1, l, r));
}
}
return 0;
} 
京公网安备 11010502036488号