做法,线段树
线段树维护一个等差序列。
懒标记:记录当前的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; }