线段树单点修改、区间修改、单点查询值、区间查询最大值、最小值、区间和之模板

毕生所学。

 1 const int N = 2e5 + 10;
 2 #define lson rt << 1      // == rt * 2     左儿子
 3 #define rson rt << 1 | 1  // == rt * 2 + 1 右儿子
 4 #define int_mid int mid = tree[rt].l + tree[rt].r >> 1
 5 int a[N]; // 初始值
 6 struct node {
 7     int l, r;
 8     ll val, lazy;
 9 } tree[N * 4];
10 void push_up(int rt) {
11     //tree[rt].val = min(tree[lson].val, tree[rson].val);
12     //tree[rt].val = max(tree[lson].val, tree[rson].val);
13     tree[rt].val = tree[lson].val + tree[rson].val;
14 }
15 void push_down(int rt) {
16     if (tree[rt].lazy) {
17         tree[lson].lazy += tree[rt].lazy;
18         tree[rson].lazy += tree[rt].lazy;
19         //{ // 维护最大最小值
20         //    tree[lson].val += tree[rt].lazy;
21         //    tree[rson].val += tree[rt].lazy;
22         //}
23         { // 维护和
24             int l = tree[rt].l, r = tree[rt].r;
25             int mid = l + r >> 1;
26             tree[lson].val += 1ll * (mid - l + 1) * tree[rt].lazy;
27             tree[rson].val += 1ll * (r - mid) * tree[rt].lazy;
28         }
29         tree[rt].lazy = 0;
30     }
31 }
32 void build(int rt, int l, int r) { // 建树
33     tree[rt].l = l, tree[rt].r = r;
34     tree[rt].lazy = 0;
35     if (l == r) {
36         tree[rt].val = a[l]; // 给定一个初始值
37         return;
38     } else {
39         int mid = l + r >> 1; // (l + r) / 2
40         build(lson, l, mid);
41         build(rson, mid + 1, r);
42         push_up(rt);
43     }
44 }
45
46 void update_point(int rt, int pos, ll val) { // 单点更新
47     if (tree[rt].l == tree[rt].r && pos == tree[rt].l) {
48         tree[rt].val += val;
49         return;
50     }
51     int_mid;
52     if (pos <= mid) update_point(lson, pos, val);
53     else update_point(rson, pos, val);
54     push_up(rt);
55 }
56
57 void update_interval(int rt, int l, int r, ll val) { // 区间更新
58     if (l <= tree[rt].l && r >= tree[rt].r) {
59         tree[rt].lazy += val;
60         //tree[rt].val += val; // 维护最大最小值
61         tree[rt].val += 1ll * (tree[rt].r - tree[rt].l + 1) * val; // 维护和
62         return;
63     }
64     push_down(rt);
65     int_mid;
66     if (l <= mid) update_interval(lson, l, r, val);
67     if (r > mid) update_interval(rson, l, r, val);
68     push_up(rt);
69 }
70
71 ll query_point(int rt, int pos) { // 单点查询
72     if (tree[rt].l == tree[rt].r && tree[rt].l == pos)
73         return tree[rt].val;
74     push_down(rt);
75     int_mid;
76     if (pos <= mid) query_point(lson, pos);
77     else query_point(rson, pos);
78 }
79
80 ll query_interval(int rt, int l, int r) { // 区间查询
81     if (l <= tree[rt].l && r >= tree[rt].r)
82         return tree[rt].val;
83     push_down(rt);
84     int_mid;
85     if (r <= mid) return query_interval(lson, l, r);
86     else if (l > mid) return query_interval(rson, l, r);
87     else {
88         //return min(query_interval(lson, l, mid), query_interval(rson, mid + 1, r));
89         //return max(query_interval(lson, l, mid), query_interval(rson, mid + 1, r));
90         return query_interval(lson, l, mid) + query_interval(rson, mid + 1, r);
91     }
92 }

原文地址:https://www.cnblogs.com/St-Lovaer/p/12245385.html

时间: 2024-11-06 14:36:18

线段树单点修改、区间修改、单点查询值、区间查询最大值、最小值、区间和之模板的相关文章

Wikioi 1082线段树成段更新成段查询

这题从昨晚搞到现在敲了又改好久,刚开始是update中错了,然后找到了.但是还错,然后因为题目没有数据的范围提示,所以弄了好久都不知道哪错了,最后看评论才知道是超int了,改了之后还有错,然后才发现虽然改成long long了,但是输出的时候没改,哈哈-- #include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <deque> #in

kb-07线段树-05-区间整体修改查询;(水)

1 /* 2 3 4 */ 5 #include<iostream> 6 #include<cstring> 7 #include<cstdio> 8 using namespace std; 9 struct P 10 { 11 int l,r,value; 12 int add; 13 }tr[400005]; 14 void Pushup(int rt) 15 { 16 tr[rt].value=tr[rt<<1].value+tr[rt<<

【数据结构】线段树 (定义 &amp; 点修改/区间查询)

[本文描述高级数据结构线段树的定义] [并解决 点修改/区间查询 的问题] 结构与定义 线段树的基本结构 ? 由图可知,线段树的每一个节点都代表着一段区间 且同一层的节点(深度相同的节点)所表示的区间互不重叠 所有叶子节点代表的区间左边界与右边界相同(叶子节点代表单个元素) 普遍规定 如果某个非叶子节点代表的区间包含元素个数为奇数 则它的左儿子包含的元素个数比右儿子大 1 在代码部分,非叶子节点表示区间为 [l,r] 则左儿子为 [ l , (l+r)/2 ] ,右儿子为 [ (l+r)/2+1

POJ 2155 二维线段树 经典的记录所有修改再统一遍历 单点查询

本来是想找一个二维线段树涉及懒惰标记的,一看这个题,区间修改,单点查询,以为是懒惰标记,敲到一半发现这二维线段树就不适合懒惰标记,你更新了某段的某列,但其实其他段的相应列也要打标记,但因为区间不一样,又不好打...也可能是我这是在套用一维线段树的思想,还有更好的二维线段树懒惰标记方法 反正到现在我还没搞定二维线段树的懒惰标记,因为这道题不用懒惰标记,因为是二进制序列,区间修改仅限于翻转操作,那就只要记录每次操作,最后查询的时候从上往下把所有修改都来上一遍,就可以了.就类似于树状数组的第二种用法,

【线段树】线段树系列 0.1单点修改单点求和线段树

终于搞定了单点修改线段树...3个月..操蛋..根本没有模板题..觉得太弱了...艹蛋...必须进一步更新我的版本啊 #include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; struct node { int left,right,value; }; node point[100]; int father[100]; int g; v

HDU(1166),线段树模板,单点更新,区间总和

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 第一次做线段树,帆哥的一句话,我记下来了,其实,线段树就是一种处理数据查询和更新的手段. 然后,我的代码风格,是网上的大牛们的辛苦总结,我就套用了.这里,我还是简单说一下线段树,说的不好,主要方便自己复习. 线段树,3个步骤,建树,查询,更新, 建树:到底部就是a[]数组的值,建立左右子树后,向上推根,根为左右子树的值 更新:类似建树,二分,找到单点所在区间,更新该区间,记得上一个区间也要变化

poj3468 splay区间修改和查询

线段树的题目,拿来练第一道splay维护区间. 像这种基本的操作修改查询,我现在应该能在20分钟手写好splay再用10分钟调试,基本上不靠模版30分钟应该能出. //#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define key_val ch[

线段树入门之单点更新

作者:zifeiy 标签:线段树 单点更新 :最最基础的线段树,只更新叶子节点,然后把信息用 push_up(int rt) 这个函数更新上来 HDU1166 敌兵布阵 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 线段树功能: update:单点增减: query:区间求和 #include <bits/stdc++.h> using namespace std; #define lson l, m, rt<<1 #def

【BZOJ3110】【Zjoi2013】K大数查询 树套树 权值线段树套区间线段树

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43020009"); } 题解: 外层权值线段树,内层区间线段树可解. 权值都是1~n,就不用离散化了. 我写了标记永久化. 其它心得神马的: 天生对树形数据结构无爱. 第一次写树套树,终于知道是怎么回事了. (只针对本题) 就是外层每个点都表示了一段

线段树第二弹(区间更新)

上篇文章,我们介绍了线段树的基本概念和单点更新.区间查询,今天,我们来接着上次的线段树问题继续深入研究.在解决线段树问题的过程中,我们会遇到要求修改区间中某一元素值的问题,当然也可能会遇到要求修改一段子区间所有值的问题--即区间更新问题.回忆一下上篇文章单点更新的方法是,由叶节点逐级向上进行更新,此时更新一个节点值的时间复杂度为o(log n),(点击链接了解详情:线段树+RMQ问题第二弹),那么以这样的处理效率来进行区间更新结果会怎样?现在假设待更新区间数据的规模为 n ,那么就需要进行 n