线段树(模板)

复制代码
 1 # include<iostream>
 2 # include<cstring>
 3 using namespace std;
 4 const int N = 2e5 + 10;
 5 
 6 struct node {
 7     int l, r;
 8     int v;
 9 } tr[4 * N]; /*存树,按照4倍储存空间储存*/
10 /*
11 线段树的存图形式为顶点为u,他的左儿子为u*2,右儿子为u*2+1
12 用位运算优化为左儿子:u<<1
13               右儿子:u<<1|1
14 */
15 void build(int u, int l, int r) {
16     /*初始化建图*/
17     tr[u] = {l, r}; /*顶点u的左右边界为[l,r]*/
18     if (l == r) return; /*如果左右边界相同,也就是说该点为顶点,而不是线段*/
19     int  mid = l + r >> 1; /*取中点*/
20     build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r); /*分别建立两段线段*/
21 }
22 
23 void pushup(int u) {
24     /*根据子节点来更新根节点的数据*/
25     tr[u].v = max(tr[u << 1].v, tr[u << 1 | 1].v); /*跟节点的值为左右节点值的最大值*/
26 }
27 
28 int query(int u, int l, int r) { /*查询*/
29     if (tr[u].l >= l && tr[u].r <= r) return tr[u].v; /*如果查找的区间在当前节点的范围内就直接返回节点的值*/
30     /*否则就查询是在左区间还是右区间*/
31     int mid = tr[u].l + tr[u].r >> 1; /*取中点,将线段分为[l,mid],[mid+1,r]两段*/
32     int v = 0;
33     if (l <= mid) v = query(u << 1, l, r); /*如果左边界小于中点则查询左边*/
34     if (r > mid) v = max(v, query(u << 1 | 1, l, r)); /*如果右边界大于中点则查询右边的最大值*/
35     /*上面步主要作用就是为了跨区间查找
36 
37         比如现在我们有两个区间[2,5],[6,10];
38 
39         而现在我们要查询[4,8]内的最大值,这时单一的左或者右已经不能够涵盖整个查询区间了,所以左右两边都要继续往下查询
40 
41         在往下查询的过程中才能找到符合的区间
42 
43       */
44     return v;
45 }
46 
47 void modify(int u, int x, int v) { /*单点修改*/
48     if (tr[u].l == x && tr[u].r == x) tr[u].v = v; /*如果该节点的左右区间都为X说明这就是要修改的单点*/
49     else { /*否则就分两段查询*/
50         int mid = tr[u].l + tr[u].r >> 1;
51         if (x <= mid) modify(u << 1, x, v); /*左边就修改左边的点*/
52         else modify(u << 1 | 1, x, v); /*右边则修改右边的点*/
53         pushup(u);/*因为子节点的值被修改,根节点的值有可能被影响,所以需要pushup更新一遍*/
54     }
55 }
56 int m, p;
57 int main() {
58     int n = 0, last = 0;
59     cin >> m >> p;
60     build(1, 1, m);
61 
62     int x;
63     char op[2];
64     while (m--) {
65         scanf("%s%d", op, &x);
66         if (*op == 'Q') { /*如果是Q则查询*/
67             last = query(1, n - x + 1, n);
68             cout << last << endl;
69         } else { /*否则就修改单点的值*/
70             modify(1, n + 1, ((long long)last + x) % p);
71             n++;/*n表示线段的最大长度*/
72         }
73     }
74 
75 
76 
77     return 0;
78 }
复制代码

 

posted @   empty_y  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示