pumpkin_porridge @ 2024-09-15 15:24:12
(我这开点有点浪费空间)
#include<iostream>
using namespace std;
int m,n;
int a[100004];
struct SegTreeNode
{
int lran,rran,val,tag_add;
SegTreeNode *left,*right;
SegTreeNode()=default;
SegTreeNode(int l,int r):lran(l),rran(r),tag_add(0),left(nullptr),right(nullptr)
{
val=0;
for(int i=lran;i<=rran;i++) val+=a[i];
}
~SegTreeNode()
{
if(left) {delete left; left=nullptr;}
if(right) {delete right; right=nullptr;}
}
void check()
{
if(!left && lran!=rran) left=new SegTreeNode(lran,(lran+rran)/2);
if(!right && lran!=rran) right=new SegTreeNode((lran+rran)/2+1,rran);
}
void pushdown()
{
if(!tag_add) return;
if(lran==rran)
{
tag_add=0;return;
}
check();
left->tag_add += tag_add;
right->tag_add += tag_add;
left->val += tag_add * (left->rran - left->lran + 1);
right->val += tag_add * (right->rran - right->lran +1);
tag_add=0;
}
};
struct SegTree
{
SegTreeNode *root;
SegTree()=default;
SegTree(int l,int r)
{
root=new SegTreeNode(l,r);
}
~SegTree()
{
delete root;
root=nullptr;
}
void add(SegTreeNode *node,int x,int y,int k)
{
if(x==node->lran && y==node->rran)
{
node->tag_add+=k;
node->val+=k*(node->rran - node->lran +1);
return;
}//lran=rran already returns here
int mid = (node->lran + node->rran)/2;
node->check();
if(y<=mid)
{
add(node->left,x,y,k);
}
else if(x>=mid+1)
{
add(node->right,x,y,k);
}
else
{
add(node->left,x,mid,k);
add(node->right,mid+1,y,k);
}
node->val = node->left->val + node->right->val;
}
int sum(SegTreeNode *node,int x,int y)
{
if(x==node->lran && y==node->rran) return node->val;//lran==rran already returns here
int mid=(node->lran + node->rran)/2;
node->check();
node->pushdown();
if(y<=mid)
{
return sum(node->left,x,y);
}
else if(x>=mid+1)
{
return sum(node->right,x,y);
}
else
{
return sum(node->left,x,mid) + sum(node->right,mid+1,y);
}
}
};
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i];
SegTree Tree(1,n);
for(int i=1;i<=m;i++)
{
int op,x,y,k;
cin>>op;
if(op==1)
{
cin>>x>>y>>k;
Tree.add(Tree.root,x,y,k);
}
if(op==2)
{
cin>>x>>y;
cout<<Tree.sum(Tree.root,x,y)<<endl;
}
}
return 0;
}
by pumpkin_porridge @ 2024-09-15 15:41:32
查了一圈,并未找到动态开点+真实指针的代码,自己尝试模仿传统代码又失败了,望大佬给点帮助
by Hagasei @ 2024-09-15 15:49:12
@pumpkin_porridge add 里没 pushdown
by Hagasei @ 2024-09-15 15:51:15
不过确实不是很建议这么写,堆式存储的线段树只需要十多行
by pumpkin_porridge @ 2024-09-15 17:47:01
还是有点不明白,仅在查询过程中进行即时的pushdown为什么不能保证该查询路径上节点信息都没有问题?@Hagasei
by Hagasei @ 2024-09-16 12:01:10
@pumpkin_porridge 对不起没看luogu,不在修改时 pushdown 会使修改在 pushup 时左右儿子的val不对,进而导致这一条链的val都失效,而如果只查询到标记节点的祖先结果就错了。可能说的有点抽象你尝试理解一下
by pumpkin_porridge @ 2024-09-19 08:56:15
(我也好久没看洛谷了) 感谢,可以理解了 @Hagasei