区间更新就是懒惰标志lazy的问题,但是这是我第一道写的,他跟一般的区间更新不同,他不是什么加减,而是直接换了每个数组元素里面的值!!!会区间更新的都应该明白
void pushdown(int node)
{
if(segtree[node].lazy!=0)
{
segtree[node<<1].lazy += segtree[node].lazy;
segtree[node<<1|1].lazy += segtree[node].lazy;
segtree[node<<1].sum += segtree[node].lazy * (segtree[node<<1].r - segtree[node<<1].l + 1);
segtree[node<<1|1].sum += segtree[node].lazy * (segtree[node<<1|1].r - segtree[node<<1|1].l + 1);
segtree[node].lazy = 0;
}
}
这是一般的区间更新,但是你真正弄懂了区间更新后,这个地方还能用+=吗?对于这道题来说,这里四个+=都要改为=!!还有好几个地方都是这个问题!所以照搬模版最无谓,一定理解思想,然后要自己写自己的代码,理解一个思想比做几道题都有用。
接下来是我AC的代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int Maxn = 100000 + 5;
int a[Maxn],val;
struct seg
{
int l,r,sum,lazy;
}segtree[Maxn*4];
void build(int node,int l,int r)
{
segtree[node].l=l;
segtree[node].r=r;
segtree[node].lazy=0;
if(l==r)
{
segtree[node].sum=a[l];
return;
}
else
{
int mid=(l+r)>>1;
build(node<<1,l,mid);
build(node<<1|1,mid+1,r);
segtree[node].sum = segtree[node<<1].sum + segtree[node<<1|1].sum;
}
}
int query(int node,int x,int y)
{
if(segtree[node].l == x && segtree[node].r == y)//包含在这个[x,y]范围内,直接返回
{
return segtree[node].sum;
}
int mid = segtree[node].l + segtree[node].r;
int res = 0;
mid >>= 1;
if(mid >= y)//[x,y]包含在左子树中
res += query(node<<1,x,y);
else if(mid < x)//[x,y]包含在右子树中
res += query(node<<1|1,x,y);
else//[x,y]在左右子树都有交集
{
res += query(node<<1,x,mid);
res += query(node<<1|1,mid+1,y);
}
return res;
}
void pushdown(int node)
{
if(segtree[node].lazy!=0)
{
segtree[node<<1].lazy = segtree[node].lazy;
segtree[node<<1|1].lazy = segtree[node].lazy;
segtree[node<<1].sum = segtree[node].lazy * (segtree[node<<1].r - segtree[node<<1].l + 1);
segtree[node<<1|1].sum = segtree[node].lazy * (segtree[node<<1|1].r - segtree[node<<1|1].l + 1);;
segtree[node].lazy = 0;
}
}
void update(int node,int x,int y)
{
if(segtree[node].l == x && segtree[node].r == y)//如果node的l和r正好就是这个x和y
{
segtree[node].lazy = val;//懒惰标记
segtree[node].sum = val * (y - x + 1);//原本都是1,sum是10,都改为2,变成20
return;//先不更新子树,segtree[node].sum已经是正确的了
}
if(segtree[node].l == segtree[node].r)//如果已经是树叶节点,就不用pushdown传递lazy下去了。否则访问非法内存空间
return;
pushdown(node);//找到一个node的懒惰标记不为0传递下去
int mid = segtree[node].l + segtree[node].r;
mid >>= 1;
if(mid >= y)
update(node<<1,x,y);
else if(mid < x)
update(node<<1|1,x,y);
else//如果卡在两个子树中间各有一段,则两个子树都要更新
{
update(node<<1,x,mid);
update(node<<1|1,mid+1,y);
}
segtree[node].sum = segtree[node<<1].sum + segtree[node<<1|1].sum;//更新子树后再来更新自己的sum
}
int main()
{
int t,n,q,l,r,i,k=1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
a[i] = 1;
build(1,1,n);
scanf("%d",&q);
while(q--)
{
scanf("%d%d%d",&l,&r,&val);
update(1,l,r);
}
printf("Case %d: The total value of the hook is %d.\n",k++,query(1,1,n));
}
return 0;
}
还是要说一句,这题写了至少三个小时,都要崩溃了,但是我还是坚持下来没去看答案自己理解了出来。