之前一直觉得自己线段树敲得很熟练,然后。。。某天。。。是的,就是我的数据结构周开始的时候我发现。。。我特么才会单点更新是怎么回事!只会区间查找是肿么回事!!摔!
恩。。。就是表达一下弱渣的心情。。。。
区间更新,用到延迟操作。
延迟操作应该是这么回事。线段树的优越性就是体现在,第一是二分查找,第二是区间操作。当我们需要多次对区间进行操作的时候,如果每次都更新每个区间内的每个节点,那么线段树的优势就不复存在啦!所以,对区间进行延迟操作,就是操作该区间的时候,标记该区间,表示操作过,但是对其子区间不进行更新。然后如果下一次我还要操作这个区间,或者是它的子区间,那么我就在对它的子区间进行上一次未完成的更新。并且下次操作是上次操作的子区间,所以一定会“经过”上次操作的区间,如果发现被标记了,表示接下来的区间未更新,就顺便在查找下次操作的区间的时候把上次操作的更新完成,并且将这种状态(操作or未操作)传递给子区间的子区间。
强烈建议画一个[1,10]的线段树,自己划两下比想一个小时管用多了。
#include <stdio.h>
#define maxn 100010
int tree[maxn<<2],col[maxn<<2];
void create(int l,int r,int rt)
{
tree[rt]=col[rt]=0;
if(l==r){tree[rt]=1;return;}
int mid=(l+r)>>1;
create(l,mid,rt<<1);create(mid+1,r,rt<<1|1);
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void pushdown(int rt,int d)
{
if(col[rt])
{
col[rt<<1]=col[rt<<1|1]=col[rt];
tree[rt<<1]=(d-(d>>1))*col[rt];
tree[rt<<1|1]=(d>>1)*col[rt];
col[rt]=0;
}
}
void update(int ll,int rr,int l,int r,int rt,int c)
{
if(ll==l&&rr==r)
{
col[rt]=c;tree[rt]=c*(r-l+1);
return;
}
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
if(rr<=mid) update(ll,rr,l,mid,rt<<1,c);
else if(ll>mid) update(ll,rr,mid+1,r,rt<<1|1,c);
else {update(ll,mid,l,mid,rt<<1,c);update(mid+1,rr,mid+1,r,rt<<1|1,c);}
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
int main()
{
int T,cas=0;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
create(1,n,1);
while(m--)
{
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
update(l,r,1,n,1,c);
}
printf("Case %d: The total value of the hook is %d.\n",++cas,tree[1]);
}
return 0;
}