线段树[模板]
来源:互联网 发布:陕西广电网络总公司 编辑:程序博客网 时间:2024/06/09 21:03
前言
线段树是一个非常实用的数据结构, 并且使用频率非常高. 所有操作都能在log时间内完成, 虽然常数要比树状数组大, 但是比起很多平衡树来说常数还是小了不少. 线段树的应用范围很广, 许多操作都能够支持.
关键是, 线段树好写好调, 完全不恶心.
除非操作非常简单, 尽量不要用树状数组. 线段树虽然代码要比树状数组大但还是很好写的, 关键是线段树要比树状数组应用范围广的多. 关于区间操作尽量用线段树.
最后要注意的就是, 能用线段树的千万不要作死去手写平衡树, 尤其是splay.
下面给出Codevs两道最简单的和操作最全的线段树.
Codevs 线段树练习
最简单滴~
#include<stdio.h>const int maxn = 1e5 + 5;typedef long long lnt;int n, q;int a[maxn];struct node{ node *ls, *rs; lnt sum; inline void update() { sum = ls->sum + rs->sum; }}pool[maxn * 4], *tail = pool, *root;node* build(int lf, int rg){ node* bt = ++tail; if(lf == rg) { bt->sum = a[lf]; return bt; } int mid = (lf + rg) >> 1; bt->ls = build(lf, mid); bt->rs = build(mid + 1, rg); bt->update(); return bt;}void modify(node* bt, int lf, int rg, int pos, int delta){ if(lf == rg) { bt->sum += delta; return; } int mid = (lf + rg) >> 1; if(pos <= mid) modify(bt->ls, lf, mid, pos, delta); else modify(bt->rs, mid + 1, rg, pos, delta); bt->update();}lnt query(node* bt, int lf, int rg, int L, int R){ if(L <= lf && rg <= R) return bt->sum; int mid = (lf + rg) >> 1; lnt rt = 0; if(L <= mid) rt += query(bt->ls, lf, mid, L, R); if(R > mid) rt += query(bt->rs, mid + 1, rg, L, R); return rt; }int main(){ scanf("%d", &n); for (int i = 1; i <= n; ++ i) scanf("%d", &a[i]); root = build(1, n); scanf("%d", &q); for (int i = 1; i <= q; ++ i) { int opt, l, r; scanf("%d%d%d", &opt, &l, &r); if(opt == 1) modify(root, 1, n, l, r); if(opt == 2) printf("%lld\n", query(root, 1, n, l, r)); }}
Codevs 线段树练习5
注意逻辑关系.
#include<stdio.h>#include<algorithm>using namespace std;typedef long long lnt;const int maxn = 1e5 + 5;const lnt inf = (lnt)1 << 62;int n, m;lnt a[maxn];char ss[maxn];struct node{ node *ls, *rs; lnt sum, fix, cmax, cmin; int flag; inline void pushdown(int lf, int rg) { if(flag == 1)// add { int mid = (lf + rg) >> 1; ls->sum += (mid - lf + 1) * fix; rs->sum += (rg - mid) * fix; ls->cmax += fix, rs->cmax += fix; ls->cmin += fix, rs->cmin += fix; if(!ls->flag) ls->flag = 1; if(!rs->flag) rs->flag = 1; ls->fix += fix, rs->fix += fix; } if(flag == 2)// val { int mid = (lf + rg) >> 1; ls->sum = (mid - lf + 1) * fix; rs->sum = (rg - mid) * fix; ls->cmax = ls->cmin = fix; rs->cmax = rs->cmin = fix; ls->flag = rs->flag = 2; ls->fix = rs->fix = fix; } flag = 0, fix = 0; } inline void update() { sum = ls->sum + rs->sum; cmax = max(ls->cmax, rs->cmax); cmin = min(ls->cmin, rs->cmin); }}pool[maxn * 4], *tail = pool, *root;node* build(int lf, int rg){ node* bt = ++tail; if(lf == rg) { bt->cmax = bt->cmin = bt->sum = a[lf]; bt->flag = bt->fix = 0; return bt; } int mid = (lf + rg) >> 1; bt->ls = build(lf, mid); bt->rs = build(mid + 1, rg); bt->flag = bt->fix = 0; bt->update(); return bt;}void modify(node* bt, int lf, int rg, int L, int R, lnt delta, int opt){ if(L <= lf && rg <= R) { if(opt) { bt->flag = 2, bt->fix = delta; bt->sum = (rg - lf + 1) * delta; bt->cmax = bt->cmin = delta; } else { bt->fix += delta; if(bt->flag != 2) bt->flag = 1; bt->sum += (rg - lf + 1) * delta; bt->cmax += delta, bt->cmin += delta; } return; } bt->pushdown(lf, rg); int mid = (lf + rg) >> 1; if(L <= mid) modify(bt->ls, lf, mid, L, R, delta, opt); if(R > mid) modify(bt->rs, mid + 1, rg, L, R, delta, opt); bt->update();}lnt query_sum(node* bt, int lf, int rg, int L, int R){ if(L <= lf && rg <= R) return bt->sum; bt->pushdown(lf, rg); int mid = (lf + rg) >> 1; lnt rt = 0; if(L <= mid) rt += query_sum(bt->ls, lf, mid, L, R); if(R > mid) rt += query_sum(bt->rs, mid + 1, rg, L, R); bt->update(); return rt;}lnt query_max(node* bt, int lf, int rg, int L, int R){ if(L <= lf && rg <= R) return bt->cmax; bt->pushdown(lf, rg); int mid = (lf + rg) >> 1; lnt rt1 = 0, rt2 = 0; if(L <= mid) rt1 = query_max(bt->ls, lf, mid, L, R); if(R > mid) rt2 = query_max(bt->rs, mid + 1, rg, L, R); bt->update(); return max(rt1, rt2);}lnt query_min(node* bt, int lf, int rg, int L, int R){ if(L <= lf && rg <= R) return bt->cmin; bt->pushdown(lf, rg); int mid = (lf + rg) >> 1; lnt rt1 = inf, rt2 = inf; if(L <= mid) rt1 = query_min(bt->ls, lf, mid, L, R); if(R > mid) rt2 = query_min(bt->rs, mid + 1, rg, L, R); bt->update(); return min(rt1, rt2);}int main(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++ i) scanf("%lld", &a[i]); root = build(1, n); for (int i = 1; i <= m; ++ i) { scanf("%s", ss); int l, r; lnt val; scanf("%d%d", &l, &r); if(ss[0] == 'a') { scanf("%lld", &val); modify(root, 1, n, l, r, val, 0); } if(ss[0] == 's' && ss[1] == 'e') { scanf("%lld", &val); modify(root, 1, n, l, r, val, 1); } if(ss[0] == 's' && ss[1] == 'u') printf("%lld\n", query_sum(root, 1, n, l, r)); if(ss[0] == 'm' && ss[1] == 'a') printf("%lld\n", query_max(root, 1, n, l, r)); if(ss[0] == 'm' && ss[1] == 'i') printf("%lld\n", query_min(root, 1, n, l, r)); }}
阅读全文
0 0
- ACM 线段树模板(模板)
- 线段树模板
- hdu_1166_线段树模板
- 线段树模板
- 线段树模板 poj2777
- 线段树模板
- 线段树模板
- 线段树-模板
- 线段树模板
- 线段树模板
- 线段树模板
- Hdu1166-- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- 线段树模板
- Unity+Vuforia实现AR图片识别应用
- noip2017 复习计划
- The best front-end hacking cheatsheets — all in one place.
- 深度学习之损失函数与激活函数的选择
- 布局改变时的过场动画
- 线段树[模板]
- 【WebService】第四章、Axis1.4发布WebService
- java反射机制
- github使用注意点
- latex 字母,字符上面 画斜线
- #BZOJ3700#发展城市(O(1)LCA+分析讨论)
- 腾讯android电话面试一
- 深度学习中的注意力机制
- vue 结合饿了么element-ui