1+ class Solution {
2+ private:
3+ using ll = long long ;
4+ const static int maxn = 1e5 +7 ;
5+ // 线段树维护区间和 涉及区间修改
6+ ll MAX[maxn<<2 ];// 表示对应的区间max 有时候需要 -- /*fill(MAX,MAX+(maxn<<2), 0);*/
7+ ll lazyMAX[maxn<<2 ];// 懒标记 表示当前区间的子区间还未被标记信息更新 这里是区间值的变动
8+ ll SUM[maxn<<2 ];// 表示对应的区间和 有时候需要 -- /*fill(SUM,SUM+(maxn<<2), 0);*/
9+ ll lazySUM[maxn<<2 ];// 懒标记 表示当前区间的子区间还未被标记信息更新 这里是区间值的变动
10+ int n,m;
11+ int lc[maxn<<2 ],rc[maxn<<2 ];// 动态开点
12+ int root=1 ,cnt=1 ;// root用于传引用,cnt记录开点数目
13+
14+ inline void pushupMAX (int &rt)
15+ {
16+ MAX[rt]= max (MAX[lc[rt]], MAX[rc[rt]]); // 父节点与子节点的关系
17+ }
18+
19+ inline void pushdownMAX (int rt,int l,int r)
20+ {
21+ if (lazyMAX[rt])
22+ {
23+ if (!lc[rt]) lc[rt]=++cnt;// 动态开点就这里不一样
24+ if (!rc[rt]) rc[rt]=++cnt;
25+ int mid=(l+r)>>1 ;
26+ lazyMAX[lc[rt]]=lazyMAX[rt];
27+ lazyMAX[rc[rt]]=lazyMAX[rt];
28+ MAX[lc[rt]]=lazyMAX[rt];
29+ MAX[rc[rt]]=lazyMAX[rt];
30+ lazyMAX[rt]=0 ;
31+ }
32+ }
33+ inline void updateMAX (int &rt,int l,int r,int vl,int vr,ll v)// rt start with root(1), [vl,vr] 区间每个数加v, [l,r] -- 总 search space
34+ {
35+ if (r<vl || l>vr) return ;
36+ if (!rt) rt=++cnt;// 动态开点 边访问边开点
37+ if (vl<=l && r<=vr)
38+ {
39+ MAX[rt]=v;
40+ lazyMAX[rt]=v;
41+ return ;
42+ }
43+ int mid=(l+r)>>1 ;
44+ pushdownMAX (rt,l,r);
45+ updateMAX (lc[rt],l,mid,vl,vr,v);
46+ updateMAX (rc[rt],mid+1 ,r,vl,vr,v);
47+ pushupMAX (rt);
48+ }
49+ inline ll queryMAX (int rt,int l,int r,int vl,int vr) // rt start with 1, query [vl,vr] 区间, [l,r] -- 总 search space
50+ {
51+ if (!rt) return LLONG_MIN;// 这个节点没有开 直接pass
52+ if (r<vl || l>vr) return LLONG_MIN;
53+ if (vl<=l && r<=vr) return MAX[rt];
54+ int mid=(l+r)>>1 ;
55+ pushdownMAX (rt,l,r);
56+ return max (queryMAX (lc[rt],l,mid,vl,vr),queryMAX (rc[rt],mid+1 ,r,vl,vr));
57+ }
58+
59+ inline void pushupSUM (int &rt)
60+ {
61+ SUM[rt]=SUM[lc[rt]]+SUM[rc[rt]]; // 父节点与子节点的关系
62+ }
63+ inline void pushdownSUM (int rt,int l,int r)
64+ {
65+ if (lazySUM[rt])
66+ {
67+ if (!lc[rt]) lc[rt]=++cnt;// 动态开点就这里不一样
68+ if (!rc[rt]) rc[rt]=++cnt;
69+ int mid=(l+r)>>1 ;
70+ lazySUM[lc[rt]]=lazySUM[rt];
71+ lazySUM[rc[rt]]=lazySUM[rt];
72+ SUM[lc[rt]]=(mid-l+1 )*lazySUM[rt];
73+ SUM[rc[rt]]=(r-mid)*lazySUM[rt];
74+ lazySUM[rt]=0 ;
75+ }
76+ }
77+ inline void updateSUM (int &rt,int l,int r,int vl,int vr,int v)// rt start with root(1), [vl,vr] 区间每个数加v, [l,r] -- 总 search space
78+ {
79+ if (r<vl || l>vr) return ;
80+ if (!rt) rt=++cnt;// 动态开点 边访问边开点
81+ if (vl<=l && r<=vr)
82+ {
83+ SUM[rt]=(r-l+1 )*v;
84+ lazySUM[rt]=v;
85+ return ;
86+ }
87+ int mid=(l+r)>>1 ;
88+ pushdownSUM (rt,l,r);
89+ updateSUM (lc[rt],l,mid,vl,vr,v);
90+ updateSUM (rc[rt],mid+1 ,r,vl,vr,v);
91+ pushupSUM (rt);
92+ }
93+ inline ll querySUM (int rt,int l,int r,int vl,int vr) // rt start with 1, query [vl,vr] 区间, [l,r] -- 总 search space
94+ {
95+ if (!rt) return 0 ;// 这个节点没有开 直接pass
96+ if (r<vl || l>vr) return 0 ;
97+ if (vl<=l && r<=vr) return SUM[rt];
98+ int mid=(l+r)>>1 ;
99+ pushdownSUM (rt,l,r);
100+ return querySUM (lc[rt],l,mid,vl,vr)+querySUM (rc[rt],mid+1 ,r,vl,vr);
101+ }
102+ };
0 commit comments