还有谁的分块跑得比线段树快?

P3372 【模板】线段树 1

我!!!
by Iniaugoty @ 2024-03-02 21:31:23


这题有更新为什么能用分块写?!
by zc_zmb @ 2024-03-03 10:57:41


@[Smiog](/user/399493) dl 能给我看看您的分块是怎么写的吗?我的线段树和分块用时一样。~~但说实话分块比线段树码量小很多~~ 这是线段树: [record](https://www.luogu.com.cn/record/149292462) code: ```cpp #include <cstdio> template <typename T, const int _size> class segment_tree { protected: int n; T tree[_size << 2], flag[_size << 2]; inline void pushup(int pos) { tree[pos] = tree[pos << 1] + tree[pos << 1 | 1]; } inline void pushdown(int pos, int mid, int l, int r) { if (flag[pos]) { tree[pos << 1] += flag[pos] * (mid - l + 1); tree[pos << 1 | 1] += flag[pos] * (r - mid); flag[pos << 1] += flag[pos]; flag[pos << 1 | 1] += flag[pos]; flag[pos] = 0; } } void build(T a[], int pos, int l, int r) { if (l == r) { tree[pos] = a[l]; return; } int mid = l + r >> 1; build(a, pos << 1, l, mid); build(a, pos << 1 | 1, mid + 1, r); pushup(pos); } void update(int pos, int l, int r, int left, int right, T v) { if (l <= left && r >= right) { tree[pos] += (right - left + 1) * v; flag[pos] += v; return; } int mid = left + right >> 1; pushdown(pos, mid, left, right); if (l <= mid) update(pos << 1, l, r, left, mid, v); if (r > mid) update(pos << 1 | 1, l, r, mid + 1, right, v); pushup(pos); } T query(int pos, int l, int r, int left, int right) { if (l <= left && r >= right) return tree[pos]; int mid = left + right >> 1; pushdown(pos, mid, left, right); T ans = 0; if (l <= mid) ans += query(pos << 1, l, r, left, mid); if (r > mid) ans += query(pos << 1 | 1, l, r, mid + 1, right); return ans; } public: segment_tree() {} ~segment_tree() {} inline void build(int N, T a[]) { n = N; build(a, 1, 1, n); } inline void update(int l, int r, T v) { update(1, l, r, 1, n, v); } inline T query(int l, int r) { return query(1, l, r, 1, n); } }; int n, m, opt, x, y; long long k, a[100005]; segment_tree<long long, 100000> tree; int main() { scanf("%d%d", &n, &m); for (register int i = 1; i <= n; ++i) scanf("%lld", a + i); tree.build(n, a); while (m--) { scanf("%d%d%d", &opt, &x, &y); if (opt == 1) { scanf("%lld", &k); tree.update(x, y, k); } else printf("%lld\n", tree.query(x, y)); } return 0; } ``` 这是分块: [record](https://www.luogu.com.cn/record/149292223) ```cpp #include <cstdio> #include <cmath> template <typename T, const int _size> class block { protected: int len, id[_size + 5]; T sum[_size + 5], data[_size + 5], flag[_size + 5]; public: inline void build(int n, T a[]) { len = sqrt(n); for (register int i = 1; i <= n; ++i) { id[i] = (i - 1) / len + 1; data[i] = a[i]; sum[id[i]] += data[i]; } } inline void modify(int L, int R, T v) { int l = id[L], r = id[R]; for (register int i = L; id[i] == l && i <= R; ++i) { data[i] += v; sum[l] += v; } if (l == r) return; for (register int i = l + 1; i < r; ++i) { flag[i] += v; sum[i] += len * v; } for (register int i = R; id[i] == r; --i) { data[i] += v; sum[r] += v; } } inline T query(int L, int R) { int l = id[L], r = id[R]; T ans = 0; for (register int i = L; id[i] == l && i <= R; ++i) ans += data[i] + flag[l]; if (l == r) return ans; for (register int i = l + 1; i < r; ++i) ans += sum[i]; for (register int i = R; id[i] == r; --i) ans += data[i] + flag[r]; return ans; } }; int n, m, opt, l, r; long long v, a[100005]; block<long long, 100000> b; int main() { scanf("%d%d", &n, &m); for (register int i = 1; i <= n; ++i) scanf("%lld", a + i); b.build(n, a); while (m--) { scanf("%d%d%d", &opt, &l, &r); if (opt == 1) { scanf("%lld", &v); b.modify(l, r, v); } else printf("%lld\n", b.query(l, r)); } return 0; } ```
by 2023gdgz01 @ 2024-03-04 14:07:22


~~本蒟佬第一次写分块~~
by 2023gdgz01 @ 2024-03-04 14:08:32


@[2023gdgz01](/user/891606) 我分块 174ms, 线段树194ms 。
by ShengXuanYi1 @ 2024-03-04 21:35:59


|