HDU4578 Transformation (多操作线段树)
终于过了这道题。。
要注意标记之间的影响,和add操作时更新求和的顺序。
same 区间每个数设置为x标记
mult 区间每个数乘x标记
add 区间每个数加x标记
①:当打same标记时,mult标记和add标记就没用了,要初始化。
②:当打mult标记时,add标记也要乘相应的值。
---------------求和可以递推过来---------------
1次方求和就正常求和
即:sum1[rt]=sum1[rt]+(r-l+1)*val;
2次方 可以由 (x+val)2 = x2+val2+2*x*val
即:sum2[rt]=sum2[rt]+2*sum1[rt]*val+(r-l+1)*val*val;
3次方 可以由 (x+val)3 = x3+val3+3*x2*val+3*x*val2
即:sum3[rt]=sum3[rt]+(r-l+1)*val*val*val+3*sum2[rt]*val+3*sum1[rt]*val*val;
再次注意 add求和要按照sum3,sum2, sum1的顺序!
算是又对取模有了一点了解。。
a*b*c*d 取模为 (a*b%mod) * (c*d%mod) %mod
a+b*c*d+3*a*b*c*d 取模为 (a + (b*c)%mod*d + 3*((a*b)%mod)*((c*d)%mod)%mod)%mod
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int mod=10007; 5 const int maxx=100010; 6 7 ll add[maxx<<2],mult[maxx<<2],same[maxx<<2]; 8 ll sum1[maxx<<2],sum2[maxx<<2],sum3[maxx<<2]; 9 10 int n,m,sum; 11 12 void pushup(int rt) { 13 sum1[rt]=(sum1[rt<<1]+sum1[rt<<1|1])%mod; 14 sum2[rt]=(sum2[rt<<1]+sum2[rt<<1|1])%mod; 15 sum3[rt]=(sum3[rt<<1]+sum3[rt<<1|1])%mod; 16 } 17 18 void build(int l,int r,int rt) { 19 add[rt]=same[rt]=0; 20 mult[rt]=1; 21 if(l==r) { 22 sum1[rt]=sum2[rt]=sum3[rt]=0; 23 return; 24 } 25 int mid=(l+r)>>1; 26 build(l,mid,rt<<1); 27 build(mid+1,r,rt<<1|1); 28 pushup(rt); 29 } 30 31 void pushdown(int rt,int len) { //下传标记 32 if(same[rt]) { 33 sum1[rt<<1]=(len-(len>>1))*same[rt]%mod; 34 sum1[rt<<1|1]=(len>>1)*same[rt]%mod; 35 sum2[rt<<1]=((len-(len>>1))*same[rt]%mod)*same[rt]%mod; 36 sum2[rt<<1|1]=((len>>1)*same[rt]%mod)*same[rt]%mod; 37 sum3[rt<<1]=((len-(len>>1))*same[rt]%mod)*(same[rt]*same[rt]%mod)%mod; 38 sum3[rt<<1|1]=((len>>1)*same[rt]%mod)*(same[rt]*same[rt]%mod)%mod; 39 same[rt<<1]=same[rt<<1|1]=same[rt]; 40 add[rt<<1]=add[rt<<1|1]=0; //也需要改变 41 mult[rt<<1]=mult[rt<<1|1]=1; //也需要改变 42 same[rt]=0; 43 } 44 if(mult[rt]!=1) { 45 mult[rt<<1]=mult[rt<<1]*mult[rt]%mod; 46 mult[rt<<1|1]=mult[rt<<1|1]*mult[rt]%mod; 47 add[rt<<1]=add[rt<<1]*mult[rt]%mod; //改变 48 add[rt<<1|1]=add[rt<<1|1]*mult[rt]%mod; //改变 49 sum1[rt<<1]=sum1[rt<<1]*mult[rt]%mod; 50 sum1[rt<<1|1]=sum1[rt<<1|1]*mult[rt]%mod; 51 sum2[rt<<1]=(sum2[rt<<1]*mult[rt]%mod)*mult[rt]%mod; 52 sum2[rt<<1|1]=(sum2[rt<<1|1]*mult[rt]%mod)*mult[rt]%mod; 53 sum3[rt<<1]=(sum3[rt<<1]*mult[rt]%mod)*(mult[rt]*mult[rt]%mod)%mod; 54 sum3[rt<<1|1]=(sum3[rt<<1|1]*mult[rt]%mod)*(mult[rt]*mult[rt]%mod)%mod; 55 mult[rt]=1; 56 } 57 if(add[rt]) { 58 add[rt<<1]=(add[rt<<1]+add[rt])%mod; 59 add[rt<<1|1]=(add[rt<<1|1]+add[rt])%mod; 60 sum3[rt<<1]=(sum3[rt<<1]+3*sum2[rt<<1]*add[rt]%mod+3*(sum1[rt<<1]*add[rt]%mod)*add[rt]%mod+(add[rt]*add[rt]%mod)*(add[rt]*(len-(len>>1))%mod))%mod; 61 sum3[rt<<1|1]=(sum3[rt<<1|1]+3*sum2[rt<<1|1]*add[rt]%mod+3*(sum1[rt<<1|1]*add[rt]%mod)*add[rt]%mod+(add[rt]*add[rt]%mod)*(add[rt]*(len>>1)%mod))%mod; 62 sum2[rt<<1]=(sum2[rt<<1]+2*sum1[rt<<1]*add[rt]%mod+(add[rt]*add[rt]%mod)*(len-(len>>1))%mod)%mod; 63 sum2[rt<<1|1]=(sum2[rt<<1|1]+2*sum1[rt<<1|1]*add[rt]%mod+(add[rt]*add[rt]%mod)*(len>>1)%mod)%mod; 64 sum1[rt<<1]=(sum1[rt<<1]+(len-(len>>1))*add[rt]%mod)%mod; 65 sum1[rt<<1|1]=(sum1[rt<<1|1]+(len>>1)*add[rt]%mod)%mod; 66 add[rt]=0; 67 } 68 } 69 70 void updata(int L,int R, int val,int op,int l,int r,int rt) { 71 if(L<=l&&R>=r) { 72 if(op==3) { 73 same[rt]=val; 74 mult[rt]=1; //改变 75 add[rt]=0; //改变 76 sum1[rt]=(r-l+1)*val%mod; 77 sum2[rt]=((r-l+1)*val%mod)*val%mod; 78 sum3[rt]=((r-l+1)*val%mod)*(val*val%mod)%mod; 79 } else if(op==2) { 80 mult[rt]=mult[rt]*val%mod; 81 add[rt]=add[rt]*val%mod; //改变 82 sum1[rt]=sum1[rt]*val%mod; 83 sum2[rt]=(sum2[rt]*val%mod)*val%mod; 84 sum3[rt]=(sum3[rt]*val%mod)*(val*val%mod)%mod; 85 } else if(op==1) { 86 add[rt]=(add[rt]+val)%mod; 87 sum3[rt]=(sum3[rt]+3*sum2[rt]*val%mod+3*(sum1[rt]*val%mod)*val%mod+(((r-l+1)*val%mod)*(val*val%mod)%mod))%mod; 88 sum2[rt]=(sum2[rt]+2*sum1[rt]*val%mod+((r-l+1)*val%mod)*val%mod)%mod; 89 sum1[rt]=(sum1[rt]+(r-l+1)*val%mod)%mod; 90 } 91 return; 92 } 93 pushdown(rt,r-l+1); 94 int mid=(l+r)>>1; 95 if(L<=mid) updata(L,R,val,op,l,mid,rt<<1); 96 if(R>mid) updata(L,R,val,op,mid+1,r,rt<<1|1); 97 pushup(rt); 98 } 99 100 ll query(int L,int R,int val,int l,int r,int rt) { 101 if(L<=l&&R>=r) { 102 if(val==1) { 103 return sum1[rt]%mod; 104 } else if(val==2) { 105 return sum2[rt]%mod; 106 } else return sum3[rt]%mod; 107 } 108 ll sum=0; 109 pushdown(rt,r-l+1); 110 int mid=(l+r)>>1; 111 if(L<=mid) sum=(sum+query(L,R,val,l,mid,rt<<1))%mod; 112 if(R>mid) sum=(sum+query(L,R,val,mid+1,r,rt<<1|1))%mod; 113 return sum; 114 } 115 116 int main() { 117 while(~scanf("%d%d",&n,&m)) { 118 if(n==0&&m==0) break; 119 build(1,n,1); 120 while(m--) { 121 int op,x,y,val; 122 scanf("%d%d%d%d",&op,&x,&y,&val); 123 if(op==4) { 124 printf("%lld\n",query(x,y,val,1,n,1)); 125 } 126 else updata(x,y,val,op,1,n,1); 127 } 128 } 129 }
埋骨何须桑梓地,人生无处不青山