初学线段树
题意要维护区间和与区间极差,这样写感觉没什么问题,老是WA,个人猜想是懒标记下放的时候极大值极小值出问题了,请大神们指点指点。





#include<iostream>
#include<algorithm>
using namespace std;
long long ans=0;
struct node
{
long long l,r,sum,max,min;
long long lazy = 0;
}tree[4000100];
void build(int l,int r,int k);
void range_view(int l, int r, int k);
void down(int k);
long long range_max(int l, int r, int k);
long long range_min(int l, int r, int k);
void addlazy(int l, int r, int K,int k);
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, q,o;
int L, R, K;
cin >> n >> q;
build(1, n, 1);
for (int i = 1; i <= q; i++)
{
cin >> o;
if (o == 1)
{
cin >> L >> R >> K;
addlazy(L, R, K,1);
continue;
}
if (o == 2)
{
cin >> L >> R;
range_view(L,R,1);
cout << ans<<endl;
ans = 0;
continue;
}
if (o == 3)
{
cin >> L >> R;
cout << range_max(L, R, 1) - range_min(L, R, 1)<<endl;
continue;
}
}
return 0;
}
void build(int l, int r, int k)
{
tree[k].l = l;
tree[k].r = r;
if (tree[k].l == tree[k].r)
{
tree[k].sum=0;
tree[k].min = 0;
tree[k].max = 0;
return;
}
int m = (l + r) / 2;
build(l, m, k << 1);
build(m + 1, r, k << 1 | 1);
tree[k].sum = tree[k << 1].sum + tree[k << 1 | 1].sum;
tree[k].max = max(tree[k << 1].max, tree[k << 1 | 1].max);
tree[k].min = min(tree[k << 1].min, tree[k << 1 | 1].min);
}
void range_view(int l, int r,int k)
{
if (tree[k].l >= l && tree[k].r <= r)
{
ans += tree[k].sum;
return;
}
if (tree[k].lazy)
down(k);
int m = (tree[k].l+tree[k].r) / 2;
if (l <= m) range_view(l,r,k<<1);
if (r > m) range_view(l,r,k << 1 | 1);
}
void down(int k)
{
tree[k << 1].lazy += tree[k].lazy;
tree[k << 1|1].lazy += tree[k].lazy;
tree[k<<1].sum += tree[k].lazy * (tree[k<<1].r - tree[k<<1].l + 1);
tree[k << 1|1].sum += tree[k].lazy * (tree[k << 1|1].r - tree[k << 1|1].l + 1);
tree[k << 1].max += tree[k].lazy;
tree[k << 1|1].max += tree[k].lazy;
tree[k << 1].min += tree[k].lazy;
tree[k << 1 | 1].min += tree[k].lazy;
tree[k].lazy = 0;
}
void addlazy(int l, int r, int K, int k)
{
if (tree[k].l >= l && tree[k].r <= r)
{
tree[k].lazy += K;
tree[k].sum += tree[k].sum * (tree[k].r - tree[k].l + 1);
tree[k].max += K;
tree[k].min += K;
return;
}
if (tree[k].lazy)
down(k);
int m = (tree[k].l + tree[k].r) / 2;
if (l <= m) addlazy(l, r, K, k << 1);
if (r > m) addlazy(l, r, K, k << 1 | 1);
tree[k].sum = tree[k << 1].sum + tree[k << 1 | 1].sum;
tree[k].max = max(tree[k << 1].max, tree[k << 1 | 1].max);
tree[k].min = min(tree[k << 1].min, tree[k << 1 | 1].min);
}
long long range_max(int l, int r, int k)
{
if (tree[k].l == l && tree[k].r == r)
{
return tree[k].max;
}
if (tree[k].lazy)
down(k);
int m = (tree[k].l + tree[k].r) / 2;
if (r <= m) return range_max(l, r, k << 1);
else if (l > m) return range_max(l, r, k << 1 | 1);
else return max(range_max(l, m, k << 1), range_max(m+1, r, k << 1 | 1));
}
long long range_min(int l, int r, int k)
{
if (tree[k].l == l && tree[k].r == r)
{
return tree[k].min;
}
if (tree[k].lazy)
down(k);
int m = (tree[k].l + tree[k].r) / 2;
if (r <= m) return range_min(l, r, k << 1);
else if (l > m) return range_min(l, r, k << 1 | 1);
else return min(range_min(l, m, k << 1), range_min(m+1, r, k << 1 | 1));
}
...全文
相关推荐
线段树的一种实现
如果线段树采用了懒惰标记策略,那么更新可以在非叶子节点上暂存,等到真正需要查询该区间的值时再进行实际计算,从而提高效率。"简单易懂"标签表明这个实现可能包含清晰的代码结构和解释,适合初学者学习。
线段树小总结
#### 总结通过上述几个例子可以看出,线段树在解决区间问题时非常有效,尤其是在需要频繁进行区间查询和更新的情况下。对于初学者来说,掌握线段树的基本构建和查询更新操作是非常重要的。
QT5实现线段树(支持鼠标绘图)
源码附带且通过了qt5编译,意味着用户可以查看和学习代码,理解其工作原理,这对于初学者来说是一份宝贵的资源。总之,这个项目结合了数据结构和图形界面编程,提供了一个直观的方式来理解和使用线段树。
线段树(acm的资料)
“树状数组线段树简单介绍”和“树状数组线段树简单理论介绍”的PPT可能详细阐述了这两种数据结构的基本原理和应用场景,帮助初学者快速理解和掌握。
线段树资料
线段树-初步学习.doc"可能是对线段树基础概念的介绍,适合初学者。"树结构在程序设计中的运用.ppt"可能涵盖了线段树以及其他树结构在编程中的应用。


其它技术问题
