首页 > 代码库 > Codeforces gym Hello 2015 Div2 B

Codeforces gym Hello 2015 Div2 B

Codeforces gym Hello 2015 Div2 B
Codeforces gym 100571 problem B
Problem
  设函数F(x),F(1)与F(2)已知,且当 i>=3,F(i)=a*F(i-2)+b*F(i-1)。再给一个长度为N的数列A,进行Q次如下操作:每次给一个区间[L, R],对于每个k(L=<k<=R),将A[k]=A[k]+F[k-L+1]。最后输出数列A(mod 10^9+7)。

Limits
Time Limit(ms): 1000
Memory Limit(MB): 256
N, Q: [1, 10^5]
F(1), F(2), a, b: [1, 10^9]
A[i]: [1, 10^9]
1=<L<=R<=N

Solution
  将每个数都表示成“t1*F(1)+t2*F(2)”的形式,设F(n)=t1*F(1)+t2*F(2),可推得F(n+1)=(a*t2)*F(1)+(t1+b*t2)*F(2)。利用“先标记最后递推维护”的思想,每次操作时,在L位置标记一个add值,在R位置标记一个sub值(具体见More中的解释);Q次操作结束后,从1到n递推一遍,不断维护每个位置的add值和A[i]值(具体见More中的解释)。最终输出A(mod 10^9+7)。

More
  对于每个位置,add与sub初始均为0,每次标记时,add[L]=add[L]+F(1) ,sub[R]=sub[R]+F(R-L+1);但,add与sub值都应表示成t1*F(1)+t2*F(2)的形式;换句话说,先需递推求出每个F(n)的系数 t1 和 t2,初始时每个add和sub的两个系数t1,t2均为0,每次标记时,add[L].t1+=F(1).t1,add[L].t2+=F(1).t2,sub[R].t1+=F(R-L+1).t1,sub[R].t2+=F(R-L+1).t2。

  Q次操作结束后,从1到n递推一遍,维护add与A[i]。先维护add,add[i].t1+=a*add[i-1].t2,add[i].t2+=add[i-1].t1+b*add[i-1].t2;再维护A[i],A[i]+=add[i].t1*F(1)+add[i].t2*F(2);再维护add,add[i].t1=add[i].t1 - sub[i].t1,add[i].t2=add[i].t2 - sub[i].t2(由于每次是维护某段[L ,R]中的权值,大于R的位置此次不可维护,所以需在R位置上标记一个sub,再适当时候将add值减去sub)。

  在维护add与A[i]时,也可以用公式F(i)=a*F(i-2)+b*F(i-1)递推维护,但其中讨论的细节有所麻烦。

Complexity
Time Complexity: O(N+Q)
Memory Complexity: O(N)

Source
Codeforces gym Hello 2015 Div2 B

Code
Codeforces gym Hello 2015 Div2 B From My Github


Codeforces gym Hello 2015 Div2 B