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 */
View Code

 

posted @ 2017-03-28 19:45  lawyer'  阅读(690)  评论(0编辑  收藏  举报