第一题
HDU1698http://acm.hdu.edu.cn/showproblem.php?pid=1698
这是在区间上进行整段的修改操作,我们就用to[]数组代表修改的lazy标记
记住在构建树和在change函数中自顶向下更新的时候,一定要注意重新回去更新上层的节点,所以末尾需加上update(cur)
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 #define N 100005 5 int sum[4*N],to[4*N]; 6 7 void update(int x) 8 { 9 sum[x]=sum[x<<1]+sum[x<<1|1]; 10 } 11 void build(int cur,int x,int y) 12 { 13 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 14 to[cur]=0; 15 if(x==y){ 16 sum[cur]=1; 17 return; 18 } 19 build(ls,x,mid); 20 build(rs,mid+1,y); 21 update(cur); 22 } 23 void pushdown(int cur,int x,int y) 24 { 25 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 26 if(to[cur]!=0){ 27 to[ls]=to[rs]=to[cur]; 28 sum[ls]=(mid-x+1)*to[cur]; 29 sum[rs]=(y-mid)*to[cur]; 30 to[cur]=0; 31 } 32 } 33 void change(int cur,int x,int y,int s,int t,int v) 34 { 35 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 36 if(x>=s&&y<=t){ 37 sum[cur]=(y-x+1)*v; 38 to[cur]=v; 39 return; 40 } 41 pushdown(cur,x,y); 42 if(mid>=s) change(ls,x,mid,s,t,v); 43 if(mid+1<=t) change(rs,mid+1,y,s,t,v); 44 update(cur); 45 } 46 void query(int cur,int x,int y,int s,int t,int &ans) 47 { 48 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 49 if(x>=s&&y<=t){ 50 ans+=sum[cur]; 51 return; 52 } 53 pushdown(cur,x,y); 54 if(mid>=s) query(ls,x,mid,s,t,ans); 55 if(mid+1<=t) query(rs,mid+1,y,s,t,ans); 56 } 57 int main() 58 { 59 int T,n,Q,a,b,c,ans; 60 scanf("%d",&T); 61 for(int i=1;i<=T;i++){ 62 ans=0; 63 scanf("%d%d",&n,&Q); 64 build(1,1,n); 65 for(int j=0;j<Q;j++){ 66 scanf("%d%d%d",&a,&b,&c); 67 change(1,1,n,a,b,c); 68 } 69 query(1,1,n,1,n,ans); 70 printf("Case %d: The total value of the hook is %d.\n",i,ans); 71 } 72 return 0; 73 }
第二题
POJ3468http://poj.org/problem?id=3468
这是在一段区间上添加值,所以与上题的操作不一样,对于每个相加的数,我们应该也不断将lazy节点累加,类似这种的累加操作,我们总是选择
用add[]数组作为lazy标记
当然这道题特别坑的是因为在累加过程中可以达到10000*100000这样子就超过了int的类型,我们就要用LL来定义sum[],add[]和ans
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 #define N 100005 6 #define LL long long 7 int a[N]; 8 LL sum[4*N],add[4*N]; 9 void update(int x) 10 { 11 sum[x]=sum[x<<1]+sum[x<<1|1]; 12 } 13 void build(int cur,int x,int y) 14 { 15 add[cur]=0; 16 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 17 if(x==y){ 18 sum[cur]=a[x]; 19 return; 20 } 21 build(ls,x,mid); 22 build(rs,mid+1,y); 23 update(cur); 24 } 25 void pushdown(int cur,int x,int y) 26 { 27 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 28 if(add[cur]!=0){ 29 add[ls]+=add[cur]; 30 add[rs]+=add[cur]; 31 sum[ls]+=(mid-x+1)*add[cur]; 32 sum[rs]+=(y-mid)*add[cur]; 33 add[cur]=0; 34 } 35 } 36 void change(int cur,int x,int y,int s,int t,int v) 37 { 38 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 39 if(x>=s&&y<=t){ 40 sum[cur]+=(y-x+1)*v; 41 add[cur]+=v; 42 return; 43 } 44 pushdown(cur,x,y); 45 if(mid>=s) change(ls,x,mid,s,t,v); 46 if(mid<t) change(rs,mid+1,y,s,t,v); 47 update(cur); 48 } 49 void query(int cur,int x,int y,int s,int t,LL &ans) 50 { 51 int mid=(x+y)/2,ls=cur<<1,rs=cur<<1|1; 52 if(x>=s&&y<=t){ 53 ans+=sum[cur]; 54 return; 55 } 56 pushdown(cur,x,y); 57 if(mid>=s) query(ls,x,mid,s,t,ans); 58 if(mid<t) query(rs,mid+1,y,s,t,ans); 59 } 60 int main() 61 { 62 int q,n,x,y,z; 63 char c; 64 while(scanf("%d%d",&n,&q)!=EOF){ 65 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 66 build(1,1,n); 67 for(int i=1;i<=q;i++){ 68 cin>>c; 69 if(c==‘C‘){ 70 scanf("%d%d%d",&x,&y,&z); 71 change(1,1,n,x,y,z); 72 } 73 else{ 74 scanf("%d%d",&x,&y); 75 LL ans=0; 76 query(1,1,n,x,y,ans); 77 printf("%I64d\n",ans); 78 } 79 } 80 } 81 return 0; 82 }
对于在线段树上修改整段区间的理解,布布扣,bubuko.com
时间: 2024-12-08 01:26:20