标签:
实现功能——1:区间加法 2:区间乘法 3:区间覆盖值 4:区间求和
这是个四种常见线段树功能的集合版哦。。。么么哒(其实只要协调好三种tag的关系并不算太难——前提是想明白了线段树的工作模式)
代码长度几经修改后也大为缩水
还有!!!——通过BZOJ1798反复的尝试,我的出来一个重要结论——尽量减少pushup操作的不必要使用次数,对于程序提速有明显的效果!!!
1 type vet=record 2 a0,a1:longint; 3 end; 4 var 5 i,j,k,l,m,n,a1,a2,a3:longint; 6 d1:vet; 7 a,b,d:array[0..100000] of longint; 8 c:array[0..100000] of vet; 9 function max(x,y:longint):longint;inline; 10 begin 11 if x>y then max:=x else max:=y; 12 end; 13 function min(x,y:longint):longint;inline; 14 begin 15 if x<y then min:=x else min:=y; 16 end; 17 function merge(d1,d2:vet):vet;inline; 18 var d3:vet; 19 begin 20 d3:=d1; 21 d3.a0:=d3.a0*d2.a0; 22 d3.a1:=d3.a1*d2.a0+d2.a1; 23 exit(d3); 24 end; 25 procedure ext(z,x,y:longint);inline; 26 begin 27 if d[z]=1 then 28 begin 29 a[z]:=b[z]*(y-x+1); 30 c[z].a0:=1;c[z].a1:=0; 31 if x<>y then 32 begin 33 b[z*2]:=b[z];d[z*2]:=1; 34 b[z*2+1]:=b[z];d[z*2+1]:=1; 35 end; 36 b[z]:=0;d[z]:=0; 37 end 38 else 39 begin 40 a[z]:=a[z]*c[z].a0+c[z].a1*(y-x+1); 41 if x<>y then 42 begin 43 if d[z*2]=1 then ext(z*2,x,(x+y) div 2); 44 if d[z*2+1]=1 then ext(z*2+1,(x+y) div 2+1,y); 45 c[z*2]:=merge(c[z*2],c[z]); 46 c[z*2+1]:=merge(c[z*2+1],c[z]); 47 end; 48 c[z].a0:=1;c[z].a1:=0; 49 end; 50 end; 51 procedure built(z,x,y:longint);inline; 52 begin 53 if x=y then 54 read(a[z]) 55 else 56 begin 57 built(z*2,x,(x+y) div 2); 58 built(z*2+1,(x+y) div 2+1,y); 59 a[z]:=a[z*2]+a[z*2+1]; 60 end; 61 b[z]:=0;d[z]:=0; 62 c[z].a0:=1;c[z].a1:=0; 63 end; 64 function op(z,x,y,l,r:longint;d1:vet):longint;inline; 65 var a2,a3:longint; 66 begin 67 if l>r then exit(0); 68 ext(z,x,y); 69 if (x=l) and (y=r) then 70 begin 71 c[z]:=d1; 72 exit((d1.a0-1)*a[z]+d1.a1*(r-l+1)); 73 end; 74 a2:=op(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2),d1); 75 a3:=op(z*2+1,(x+y) div 2+1,y,max(l,(x+y) div 2+1),r,d1); 76 a[z]:=a[z]+a2+a3; 77 exit(a2+a3); 78 end; 79 function cover(z,x,y,l,r,p:longint):longint;inline; 80 var a2,a3:longint; 81 begin 82 if l>r then exit(0); 83 ext(z,x,y); 84 if (x=l) and (y=r) then 85 begin 86 d[z]:=1;b[z]:=p; 87 exit(p*(r-l+1)-a[z]); 88 end; 89 a2:=cover(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2),p); 90 a3:=cover(z*2+1,(x+y) div 2+1,y,max(l,(x+y) div 2+1),r,p); 91 a[z]:=a[z]+a2+a3; 92 exit(a3+a2); 93 end; 94 function cal(z,x,y,l,r:longint):longint; 95 begin 96 if l>r then exit(0); 97 ext(z,x,y); 98 if (x=l)and (y=r) then exit(a[z]); 99 exit(cal(z*2,x,(x+y) div 2,l,min(r,(x+y) div 2))+cal(z*2+1,(x+y) div 2+1,y,max(l,(x+y) div 2+1),r)); 100 end; 101 begin 102 readln(n,m); 103 built(1,1,n); 104 readln; 105 for i:=1 to m do 106 begin 107 read(j); 108 case j of 109 1:begin //区间加 110 readln(a1,a2,a3); 111 d1.a0:=1;d1.a1:=a3; 112 op(1,1,n,a1,a2,d1); 113 end; 114 2:begin //区间乘 115 readln(a1,a2,a3); 116 d1.a0:=a3;d1.a1:=0; 117 op(1,1,n,a1,a2,d1); 118 end; 119 3:begin //区间覆盖值 120 readln(a1,a2,a3); 121 cover(1,1,n,a1,a2,a3); 122 end; 123 4:begin //区间求和 124 readln(a1,a2); 125 writeln(cal(1,1,n,a1,a2)); 126 end; 127 else halt; 128 end; 129 end; 130 end. 131
算法模板——线段树4(区间加+区间乘+区间覆盖值+区间求和)
标签:
原文地址:http://www.cnblogs.com/HansBug/p/4237659.html