算是我真正意义上的区间更新的第一题,我是这样理解区间更新的:
为了节省时间,在更新区间的时候不必每次都更新到叶子节点。如果当前节点的的区间被包含在查询区间内,就暂时只更新这个节点。但是如果仅仅这样,将来在下次更新的时候,如果涉及了该节点的孩子节点,就会出错。
所以有一个办法:在更新的时候,如果我们明确知道了该节点的儿子节点涉及到了将要更新的区间,就事先把它的左右儿子节点按照父节点的val更新了,由于更新是递归实现的,所以如果它的孙子节点也涉及了,孙子节点会在儿子节点的递归层被更新。
这样做肯定比每次都更新到叶子节点大大节省了时间。
AC代码:
/* ***********************************************
Author :angon
************************************************ */
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
HDU 1689
线段树
成段更新
*/
#include
#include
#include
#include
using namespace std;
const int MAXN=100010;
struct Node
{
int l,r;
int lazy,tag;
int sum;
}segTree[MAXN*3];
void Build(int i,int l,int r)
{
segTree[i].l=l;
segTree[i].r=r;
segTree[i].lazy=0;
segTree[i].tag=0;
if(l==r)
{
segTree[i].sum=1;
return;
}
int mid=(l+r)>>1;
Build(i<<1,l,mid);
Build((i<<1)|1,mid+1,r);
segTree[i].sum=segTree[i<<1].sum+segTree[(i<<1)|1].sum;
}
void update(int i,int l,int r,int v)
{
if(segTree[i].l==l&&segTree[i].r==r)//成段更新
{
segTree[i].lazy=1;
segTree[i].tag=v;
segTree[i].sum=(r-l+1)*v;
return;
}
int mid=(segTree[i].l+segTree[i].r)>>1;
if(segTree[i].lazy==1)
{
segTree[i].lazy=0;
update(i<<1,segTree[i].l,mid,segTree[i].tag);
update((i<<1)|1,mid+1,segTree[i].r,segTree[i].tag);
segTree[i].tag=0;
}
if(r<=mid) update(i<<1,l,r,v);
else if(l>mid)update((i<<1)|1,l,r,v);
else
{
update(i<<1,l,mid,v);
update((i<<1)|1,mid+1,r,v);
}
segTree[i].sum=segTree[i<<1].sum+segTree[(i<<1)|1].sum;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int x,y,z;
int n;
int m;
int T;
scanf("%d",&T);
int iCase=0;
while(T--)
{
iCase++;
scanf("%d%d",&n,&m);
Build(1,1,n);
while(m--)
{
scanf("%d%d%d",&x,&y,&z);
update(1,x,y,z);
}
printf("Case %d: The total value of the hook is %d.\n",iCase,segTree[1].sum);
}
return 0;
}