题目大意:首先区间1-N的数都是1,然后让你把区间a-b的值改变为c;
思路:裸的区间更新。比单点更新就是多了一个标记的la[]数组,用来代表在某个区间的数需要给便成la[],
其具体的用法就是,在创建线段树的同时要la[]数组清空。在区间改变时将改变的量赋值给la[],然后把la[]数组下放
对于此题,是将所有la[]的左右孩子都直接改变为la[]的值即可。然后改变左右孩子的sum[],有两种情况:左孩子和
sum[rt<<1]=la[rt]*(len-(len/2)),右孩子和sum[rt<<1|1]=la[rt]*(m/2);即当前的改变量la[]×区间的长度。最后要将当前节点的la[]标记消掉。(PS:线段数的数组大小在至少开原叶子点数的4倍,因为线段树其实就是一个完全的二叉树)。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#define LL long long
#define inf 0x3f3f3f3f
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define M 1000100
using namespace std;
int sum[M*4],n,la[M*4];
void up(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void bu(int l,int r,int rt)
{
la[rt]=0;
if(l==r)
{
sum[rt]=1;
return ;
}
int mid=(l+r)>>1;
bu(ls);
bu(rs);
up(rt);
}
void down(int rt,int m)
{
if(la[rt])
{
la[rt<<1]=la[rt<<1|1]=la[rt];
sum[rt<<1]=la[rt]*(m-(m>>1) );
sum[rt<<1|1]=la[rt]*(m>>1);
la[rt]=0;
}
}
void ch(int a,int b,int c,int l,int r,int rt)
{
if(l>=a&&r<=b)
{
la[rt]=c;
sum[rt]=c*(r-l+1);
return ;
}
down(rt,r-l+1);
int mid=(l+r)>>1;
if(a<=mid)
ch(a,b,c,ls);
if(mid<b)
ch(a,b,c,rs);
up(rt);
}
int main()
{
int m,i,j,k,cla,a,b,c;
scanf("%d",&cla);
for(int gr=1;gr<=cla;gr++)
{
scanf("%d",&n);
bu(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
ch(a,b,c,1,n,1);
}
printf("Case %d: The total value of the hook is %d.\n",gr,sum[1]);
}
return 0;
}