题目大意:首先区间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; }