RainbowSheep_ @ 2024-10-21 19:15:51
好像我这份代码才会出现这种问题
还有,为什么要在每次区间操作的时候都要 pushdown.... 附代码:
//https://www.luogu.com.cn/problem/P3372
#include <iostream>
using namespace std;
#define MAX 100010
#define ROOT 1
struct segment
{
int l,r;
long long val,lazy;
}segtree[MAX*4];
int a[MAX],n,m,x,y,op;
long long k;
void build(int p,int l,int r)
{
segtree[p].l=l;
segtree[p].r=r;
if(l==r)
{
segtree[p].val=a[l];
return;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
segtree[p].val=segtree[p*2].val+segtree[p*2+1].val;
}
inline void pd(int p)
{
if(!segtree[p].lazy)
return;
if(segtree[p].l!=segtree[p].r)
{
segtree[p*2].lazy+=segtree[p].lazy;
segtree[p*2+1].lazy+=segtree[p].lazy;
}
segtree[p*2].val+=segtree[p].lazy*(segtree[p*2].r-segtree[p*2].l+1);
segtree[p*2+1].val+=segtree[p].lazy*(segtree[p*2+1].r-segtree[p*2+1].l+1);
segtree[p].lazy=0;
}
void add(long long x,int l,int r,int p=ROOT)
{
pd(p);
// cout << segtree[p].l << ',' << segtree[p].r << ':' << segtree[p].val << endl;
if(l<=segtree[p].l&&r>=segtree[p].r)
{
segtree[p].val+=x*(segtree[p].r-segtree[p].l+1);
segtree[p].lazy+=x;
// cout << segtree[p].l << ',' << segtree[p].r << ':' << segtree[p].val << endl;
return;
}
int mid=(segtree[p].l+segtree[p].r)/2;
if(r<=mid)
add(x,l,r,p*2);
else if(l>mid)
add(x,l,r,p*2+1);
else
{
add(x,l,r,p*2);
add(x,l,r,p*2+1);
}
segtree[p].val=segtree[p*2].val+segtree[p*2+1].val;
// cout << segtree[p].l << ',' << segtree[p].r << ':' << segtree[p].val << endl;
}
long long query(int l,int r,int p=ROOT)
{
pd(p);
if(l<=segtree[p].l&&r>=segtree[p].r)
return segtree[p].val;
int mid=(segtree[p].l+segtree[p].r)/2;
if(r<=mid)
return query(l,r,p*2);
else if(l>mid)
return query(l,r,p*2+1);
return query(l,r,p*2)+query(l,r,p*2+1);
}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for(int i = 1;i<=n;i++)
cin >> a[i];
build(ROOT,1,n);
while(m--)
{
cin >> op >> x >> y;
switch(op)
{
case 1:
cin >> k;
add(k,x,y);
break;
case 2:
cout << query(x,y) << endl;
}
}
return 0;
}
by Hagasei @ 2024-10-21 19:18:08
这个写法线段树数组得开到 8n。
by RainbowSheep_ @ 2024-10-21 19:18:34
@Hagasei 为什么呢 orz
by SegmentTree_ @ 2024-10-21 19:20:54
@RainbowSheep_ 你pushdown
判叶子节点那里要把下面两行也放进去啊,你这样到了叶子节点也会继续传,空间就翻倍了,还有正常的线段树要开4n。
by MutU @ 2024-10-21 19:21:43
因为线段树要开四倍空间
不然呢
by Hagasei @ 2024-10-21 19:21:47
首先线段树结点数量是 2n,编号最大值是 4n。但是你的写法在叶子结点也会 pushdown 导致他的儿子编号达到了 8n。
其实当条件 l<=segtree[p].l&&r>=segtree[p].r
成立的时候就不用 pushdown 了,因为你的 pushdown 是更新儿子结点信息,而当前结点的信息是正确的。
将 pushdown 放在退出判断后面还有个好处是 pushdown 内部不用判断是不是叶子了,因为不可能。
by RainbowSheep_ @ 2024-10-21 19:22:47
@tianyu_awa 明白了,谢谢大佬 orz
by RainbowSheep_ @ 2024-10-21 19:24:39
@Hagasei 明白了,谢谢大佬
by ZMQ_Ink6556 @ 2024-10-21 21:29:06
@Hagasei 线段树的极限节点数量是
by Hagasei @ 2024-10-22 07:45:02
@ZMQ_Ink6556 bruh 很明显我在说数量级啊。结点编号最大值也不是 4n 啊。
by ZMQ_Ink6556 @ 2024-10-22 07:48:58
@Hagasei 省略常数项节点数为