Transformation
题意:
给一初始为0的数列,要求进行,区间$set,add,multiply$,维护 $\sum{{a_i}^{p}}$ (0<=p<=3)
解法:
首先考虑区间加c的影响,记$S(p)$表示当前区间的$\sum{{a_i}^p}$
这样有,$$\sum{(a_i + c)^p} = \sum_{r=0}^p{C_p^r S(p-r) c^r}$$。
这样我们只要维护 3 个标记 $set,add,multiply$ 即可,
考虑标记的合并方式。
首先只看$add,multiply$,记$qv$为当前操作的数值,
这样有$sum' = multiply \times sum + add$
将一个乘以$qv$的标记推下来有:$sum' = (qv \cdot multiply) \times sum + (add \cdot qv)$
将一个加上$qv$的标记推下来有:$sum' = multiply \times sum + (add+qv)$
注意我们每个点可能同时存在 $add, multiply$ ,这样要先下推 $multiply$。
考虑$set$标记,$set$标记可以覆盖其他的所有标记,而其他的标记和$set$合并后都可以表示为一个$set$标记。
PS:注意在叶子节点不要push(多组数据的时候会错)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 5 #define N 100010 6 #define l(x) ch[x][0] 7 #define r(x) ch[x][1] 8 #define P 10007 9 10 using namespace std; 11 12 int n,m,totn; 13 int ch[N<<1][2],sumv[N<<1][4]; 14 int addv[N<<1],mulv[N<<1],setv[N<<1]; 15 int C[5][5]; 16 17 void push(int x) 18 { 19 if(setv[x]!=-1) 20 { 21 setv[l(x)]=setv[x]; 22 addv[l(x)]=0; 23 mulv[l(x)]=1; 24 25 setv[r(x)]=setv[x]; 26 addv[r(x)]=0; 27 mulv[r(x)]=1; 28 29 int tmp=setv[x]; 30 for(int i=1;i<=3;i++) 31 { 32 sumv[l(x)][i] = sumv[l(x)][0]*tmp%P; 33 sumv[r(x)][i] = sumv[r(x)][0]*tmp%P; 34 tmp = tmp*setv[x]%P; 35 } 36 setv[x]=-1; 37 } 38 if(mulv[x]!=1) 39 { 40 if(setv[l(x)]==-1) 41 { 42 mulv[l(x)] = mulv[l(x)]*mulv[x]%P; 43 addv[l(x)] = addv[l(x)]*mulv[x]%P; 44 } 45 else setv[l(x)] = setv[l(x)]*mulv[x]%P; 46 47 if(setv[r(x)]==-1) 48 { 49 mulv[r(x)] = mulv[r(x)]*mulv[x]%P; 50 addv[r(x)] = addv[r(x)]*mulv[x]%P; 51 } 52 else setv[r(x)] = setv[r(x)]*mulv[x]%P; 53 int tmp=mulv[x]; 54 55 for(int i=1;i<=3;i++) 56 { 57 sumv[l(x)][i] = sumv[l(x)][i]*tmp%P; 58 sumv[r(x)][i] = sumv[r(x)][i]*tmp%P; 59 tmp = tmp*mulv[x]%P; 60 } 61 62 mulv[x]=1; 63 } 64 if(addv[x]) 65 { 66 int Sl[4],Sr[4]; 67 memcpy(Sl,sumv[l(x)],sizeof(sumv[l(x)])); 68 memcpy(Sr,sumv[r(x)],sizeof(sumv[r(x)])); 69 70 for(int i=1;i<=3;i++) 71 { 72 int tmp=1; 73 sumv[l(x)][i]=0; 74 sumv[r(x)][i]=0; 75 for(int j=0;j<=i;j++) 76 { 77 sumv[l(x)][i] += C[i][j]*tmp%P*Sl[i-j]%P; 78 if(sumv[l(x)][i]>=P) sumv[l(x)][i]-=P; 79 sumv[r(x)][i] += C[i][j]*tmp%P*Sr[i-j]%P; 80 if(sumv[r(x)][i]>=P) sumv[r(x)][i]-=P; 81 tmp = tmp*addv[x]%P; 82 } 83 } 84 85 if(setv[l(x)]==-1) addv[l(x)] = (addv[l(x)]+addv[x])%P; 86 else setv[l(x)] = (setv[l(x)]+addv[x])%P; 87 if(setv[r(x)]==-1) addv[r(x)] = (addv[r(x)]+addv[x])%P; 88 else setv[r(x)] = (setv[r(x)]+addv[x])%P; 89 addv[x]=0; 90 } 91 } 92 93 void update(int x) 94 { 95 sumv[x][0]=(sumv[l(x)][0]+sumv[r(x)][0])%P; 96 sumv[x][1]=(sumv[l(x)][1]+sumv[r(x)][1])%P; 97 sumv[x][2]=(sumv[l(x)][2]+sumv[r(x)][2])%P; 98 sumv[x][3]=(sumv[l(x)][3]+sumv[r(x)][3])%P; 99 } 100 101 int build(int l,int r) 102 { 103 int x=++totn; 104 addv[x]=0; 105 mulv[x]=1; 106 setv[x]=-1; 107 memset(sumv[x],0,sizeof(sumv[x])); 108 if(l==r) 109 { 110 sumv[x][0]=1; 111 l(x)=0; 112 r(x)=0; 113 return x; 114 } 115 int mid=(l+r)>>1; 116 l(x)=build(l,mid); 117 r(x)=build(mid+1,r); 118 update(x); 119 return x; 120 } 121 122 void add(int x,int l,int r,int ql,int qr,int qv) 123 { 124 push(x); 125 if(ql<=l && r<=qr) 126 { 127 addv[x] = qv; 128 int S[4]; 129 memcpy(S,sumv[x],sizeof(sumv[x])); 130 for(int i=1;i<=3;i++) 131 { 132 int tmp=1; 133 sumv[x][i]=0; 134 for(int j=0;j<=i;j++) 135 { 136 sumv[x][i] += C[i][j] * tmp %P * S[i-j]%P; 137 if(sumv[x][i]>=P) sumv[x][i]-=P; 138 tmp = tmp*qv%P; 139 } 140 } 141 return; 142 } 143 int mid=(l+r)>>1; 144 if(ql<=mid) add(l(x),l,mid,ql,qr,qv); 145 if(mid<qr) add(r(x),mid+1,r,ql,qr,qv); 146 update(x); 147 } 148 149 void mul(int x,int l,int r,int ql,int qr,int qv) 150 { 151 push(x); 152 if(ql<=l && r<=qr) 153 { 154 mulv[x] = qv; 155 int tmp=qv; 156 for(int i=1;i<=3;i++) 157 { 158 sumv[x][i] = sumv[x][i]*tmp%P; 159 tmp = tmp*qv%P; 160 } 161 return; 162 } 163 int mid=(l+r)>>1; 164 if(ql<=mid) mul(l(x),l,mid,ql,qr,qv); 165 if(mid<qr) mul(r(x),mid+1,r,ql,qr,qv); 166 update(x); 167 } 168 169 void setd(int x,int l,int r,int ql,int qr,int qv) 170 { 171 push(x); 172 if(ql<=l && r<=qr) 173 { 174 setv[x] = qv; 175 int tmp=qv; 176 for(int i=1;i<=3;i++) 177 { 178 sumv[x][i] = sumv[x][0]*tmp%P; 179 tmp = tmp*qv%P; 180 } 181 return; 182 } 183 int mid=(l+r)>>1; 184 if(ql<=mid) setd(l(x),l,mid,ql,qr,qv); 185 if(mid<qr) setd(r(x),mid+1,r,ql,qr,qv); 186 update(x); 187 } 188 189 int ask(int x,int l,int r,int ql,int qr,int qk) 190 { 191 push(x); 192 if(ql<=l && r<=qr) return sumv[x][qk]; 193 int mid=(l+r)>>1,ans=0; 194 if(ql<=mid) ans += ask(l(x),l,mid,ql,qr,qk); 195 if(mid<qr) 196 { 197 ans += ask(r(x),mid+1,r,ql,qr,qk); 198 if(ans>=P) ans-=P; 199 } 200 update(x); 201 return ans; 202 } 203 204 int main() 205 { 206 C[0][0]=1; 207 for(int i=1;i<=3;i++) 208 { 209 C[i][0]=1; 210 for(int j=1;j<=i;j++) 211 C[i][j] = (C[i-1][j-1]+C[i-1][j])%P; 212 } 213 while(scanf("%d%d",&n,&m), n&&m) 214 { 215 totn=0; 216 build(1,n); 217 int cmd,l,r,x; 218 while(m--) 219 { 220 scanf("%d%d%d%d",&cmd,&l,&r,&x); 221 if(cmd==1) add(1,1,n,l,r,x%P); 222 else if(cmd==2) mul(1,1,n,l,r,x%P); 223 else if(cmd==3) setd(1,1,n,l,r,x%P); 224 else printf("%d\n",ask(1,1,n,l,r,x)); 225 } 226 } 227 return 0; 228 } 229 /* 230 5 5 231 3 3 5 7 232 1 2 4 4 233 4 1 5 2 234 2 2 5 8 235 4 3 5 3 236 0 0 237 */