無聊的數列
阿新 • • 發佈:2020-10-05
sol:
線段樹維護等差數列。lazy_tag維護首項和公差。pushdown時將首項和公差累加到子節點上去。應重新計算右節點的首項。
#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 1e5 + 100; struct Tree { int l, r; int v, fir, d; } tr[N << 2]; int n, m; int a[N]; void build(int u, int l, int r) { tr[u].l = l, tr[u].r = r; if( l == r) { tr[u].v = a[l]; return; } int mid = tr[u].l + tr[u].r >> 1; build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); } void pushdown(int u) { if( tr[u].fir || tr[u].d) { Tree & ls = tr[u << 1], &rs = tr[u << 1 | 1]; ls.fir += tr[u].fir; ls.d += tr[u].d; ls.v += tr[u].fir; int first = tr[u].fir + (ls.r - ls.l + 1) * tr[u].d;//右側的首項 rs.fir += first; rs.d += tr[u].d; rs.v += first; tr[u].d = 0; tr[u].fir = 0; } } void change(int u, int l, int r, int k, int d) { if( tr[u].l >= l && tr[u].r <= r) { int first = k + (tr[u].l - l) * d; tr[u].fir += first; tr[u].d += d; tr[u].v += first; return; } pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if( l <= mid) change(u << 1, l, r, k, d); if( r > mid) change(u << 1 | 1, l, r, k, d); } int query(int u, int k) { if( tr[u].l == tr[u].r) { return tr[u].v; } pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if( k <= mid) return query(u << 1, k); else return query(u << 1 | 1, k); } int main() { // freopen("E:\\data.in.txt", "r", stdin); // freopen("E:\\data.out.txt", "w", stdout); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i ++) { scanf("%d", &a[i]); } build(1, 1, n); while(m --) { int opt, l, r, k, d; scanf("%d", &opt); if( opt == 1) { scanf("%d%d%d%d", &l, &r, &k, &d); change(1, l, r, k, d); } else { scanf("%d", &k); printf("%d\n", query(1, k)); } } return 0; }