线段树~总结下吧
为什么我比较喜欢线段树呢
因为线段树容易写,万一写错了还容易调试
能以优秀的效率完成一些比较水的操作
如:
单点更新(增减, 替换等)O(logn)
查询区间(最值,求和等 )O(logn)
但只能查询区间的话明显是不够的
而修改区间用单点更新的方法复杂度就不再优了
于是我们引进一种lazy标记, 也可以叫可持续化
这个时候再谈修改区间, 无论是替换, 增减, 求和, 异或就无压力了
至于区间的合并与离散化扫描线也不在话下
贴段code吧
我习惯写我最爱的大常数版堆式线段树
simple
#include <ctime>#include <cstdio>#include <cstdlib>#include <iostream>using namespace std;const int maxn = 100000 + 5;class Interval_tree{ public : Interval_tree() { memset(a, 0, sizeof(a)); memset(l, 0, sizeof(l)); memset(r, 0, sizeof(r)); memset(lazy, 0, sizeof(lazy)); } void pushup(int rt) { a[rt] = a[rt << 1] + a[rt << 1 | 1]; } void pushdown(int rt, int wh) { if (lazy[rt] != 0) { lazy[rt << 1] += lazy[rt]; lazy[rt << 1 | 1] += lazy[rt]; a[rt << 1] += lazy[rt] * (wh - (wh >> 1)); a[rt << 1 | 1] += lazy[rt] * (wh >> 1); lazy[rt] = 0; } } void buildtree(int rt) { if (l[rt] == r[rt]) { scanf("%lld", &a[rt]); return; } int mid = (l[rt] + r[rt]) >> 1; l[rt << 1] = l[rt]; r[rt << 1] = mid; l[rt << 1 | 1] = mid + 1; r[rt << 1 | 1] = r[rt]; if (l[rt] <= mid) buildtree(rt << 1); if (r[rt] > mid) buildtree(rt << 1 | 1); pushup(rt); } void Insert(int x, int y, int k, int rt) { if (x <= l[rt] && y >= r[rt]) { lazy[rt] += k; a[rt] += (long long)k * (r[rt] - l[rt] + 1); return; } pushdown(rt, r[rt] - l[rt] + 1); int mid = (l[rt] + r[rt]) >> 1; if (x <= mid) Insert(x, y, k, rt << 1); if (y > mid) Insert(x, y, k, rt << 1 | 1); pushup(rt); } long long Query(int x, int y, int rt) { if (x <= l[rt] && y >= r[rt]) return a[rt]; pushdown(rt, r[rt] - l[rt] + 1); int mid = (l[rt] + r[rt]) >> 1; long long ans = 0; if (x <= mid) ans += Query(x, y, rt << 1); if (y > mid) ans += Query(x, y, rt << 1 | 1); return ans; } void initialize() { cin >> n >> m; l[1] = 1; r[1] = n; buildtree(1); for (int i = 1; i <= m; ++i) { char ch; int x, y, k; scanf("\n%c", &ch); if (ch == 'Q') { scanf("%d%d", &x, &y); long long Ans = Query(x, y, 1); printf("%lld\n", Ans); } else if (ch == 'C') { scanf("%d%d%d", &x, &y, &k); Insert(x, y, k, 1); } } } private : int n, m; long long a[maxn << 2]; int l[maxn << 2], r[maxn << 2]; long long lazy[maxn << 2];};Interval_tree interval_tree;int main(){ freopen("simple.in", "r", stdin); freopen("simple.out", "w", stdout); interval_tree.initialize(); return 0;}
另吐槽下cuizimu奇葩的类写法, 在类内声明, 要封装的函数全写外面。
且还用drj的写法和我一样的神D来D我。