Codeforces Round #373 (Div. 2)E. Sasha and Array +线段树+矩阵快速幂

题目连接:E. Sasha and Array

题意:给一个数组,两种操作,第一种给区间[l,r]的值都加上x,第二种求区间[l,r],每一项对应的fib数之和,

题解:第一种操作很好解决用个线段树加个laz标记就可以了,但是求和就不好做了,我们求某一项的fib数可以用矩阵快速幂求出。所以我们把线段树的每一个node有看成矩阵,所以对某一区间加x,就是把这区间的每个矩阵都乘矩阵{0,1;1,1;}的x次幂;把laz也换成矩阵,然后其他操作就是裸的线段树。

参考博客:https://www.cnblogs.com/qscqesze/p/5902547.html

  1 #include<bits/stdc++.h>
  2 #include<set>
  3 #include<cstdio>
  4 #include<iomanip>
  5 #include<iostream>
  6 #include<string>
  7 #include<cstring>
  8 #include<algorithm>
  9 #define pb push_back
 10 #define mk make_pair
 11 #define ll long long
 12 #define fi first
 13 #define se second
 14 #define PI 3.14159265
 15 #define ls l,m,rt<<1
 16 #define rs m+1,r,rt<<1|1
 17 #define eps 1e-7
 18 #define pii pair<int,int>
 19 typedef unsigned long long ull;
 20 const int mod=1e9+7;
 21 const ll inf=0x3f3f3f3f3f3f3f;
 22 const int maxn=1e5+5;
 23 using namespace std;
 24 struct mat
 25 {
 26     int n, m;
 27     ll a[2][2];
 28     mat() {}
 29     void init(int _n, int _m)
 30     {
 31         n = _n;
 32         m = _m;
 33         for(int i = 0; i < n; i++)
 34         {
 35             for(int j = 0; j < m; j++) a[i][j] = 0;
 36         }
 37     }
 38     void one()
 39     {
 40         init(2,2);a[0][0]=1;a[1][1]=1;
 41     }
 42     mat operator + (const mat &B)const
 43     {
 44         mat C;
 45         C.init(n,m);
 46         for(int i=0; i<n; i++)
 47             for(int j=0; j<m; j++)
 48                 C.a[i][j]=(a[i][j]+B.a[i][j])%mod;
 49         return C;
 50     }
 51     mat operator*(const mat &P)const
 52     {
 53         mat ret;
 54         ret.init(n,m);
 55         for(int i = 0; i < n; i++)
 56         {
 57             for(int k = 0; k < m; k++)
 58             {
 59                 if(a[i][k])
 60                 {
 61                     for(int j = 0; j < P.m; j++)
 62                     {
 63                         ret.a[i][j] = ((ll)a[i][k] * P.a[k][j] + ret.a[i][j]) % mod;
 64                     }
 65                 }
 66             }
 67         }
 68         return ret;
 69     }
 70     mat operator^(const ll &P)const
 71     {
 72         ll num = P;
 73         mat ret, tmp = *this;
 74         ret.init(n,m);
 75         for(int i = 0; i < n; i++) ret.a[i][i] = 1;
 76         while(num)
 77         {
 78             if(num & 1) ret = ret * tmp;
 79             tmp = tmp * tmp;
 80             num >>= 1;
 81         }
 82         return ret;
 83     }
 84 };
 85 ll a[maxn];int n,m;
 86 mat sum[maxn<<2],laz[maxn<<2];
 87 bool flag[maxn<<2];
 88 void push_up(int rt)
 89 {
 90     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 91 }
 92 void built(int l,int r,int rt)
 93 {   sum[rt].init(2,2);laz[rt].one();flag[rt]=0;
 94     if(l==r)
 95     {
 96         mat t;t.init(2,2);t.a[0][0]=0;t.a[0][1]=1;t.a[1][1]=1;t.a[1][0]=1;
 97         sum[rt]=t^a[l];return ;
 98     }
 99     int m=(l+r)>>1;
100     built(ls);built(rs);
101     push_up(rt);
102 }
103 void push_down(int rt)
104 {
105     if(flag[rt])
106     {
107         sum[rt<<1]=sum[rt<<1]*laz[rt];
108         laz[rt<<1]=laz[rt<<1]*laz[rt];
109         sum[rt<<1|1]=sum[rt<<1|1]*laz[rt];
110         laz[rt<<1|1]=laz[rt<<1|1]*laz[rt];
111         flag[rt<<1]=flag[rt<<1|1]=1;
112         laz[rt].one();
113         flag[rt]=0;
114     }
115 }
116 void update(int L,int R,mat v,int l,int r,int rt)
117 {
118    if(L<=l&&r<=R)
119    {
120       laz[rt]=laz[rt]*v;
121       sum[rt]=sum[rt]*v;
122       flag[rt]=1;
123       return ;
124    }
125    push_down(rt);
126    int m=(l+r)>>1;
127    if(L<=m)update(L,R,v,ls);
128    if(R>m)update(L,R,v,rs);
129    push_up(rt);
130 }
131 mat  query(int L,int R,int l,int r,int rt)
132 {
133     if(L<=l&&r<=R) return sum[rt];
134     push_down(rt);
135     int m=(l+r)>>1;
136     mat ans;ans.init(2,2);
137     if(L<=m)ans=ans+query(L,R,ls);
138     if(R>m)ans=ans+query(L,R,rs);
139     push_up(rt);
140     return ans;
141 }
142 int main()
143 {
144     scanf("%d %d",&n,&m);
145     for(int i=1;i<=n;i++)scanf("%d",a+i);
146     built(1,n,1);
147     while(m--)
148     {
149         int op,l,r,v;
150         scanf("%d",&op);
151         if(op==2)
152         {
153             scanf("%d %d",&l,&r);
154             printf("%lld
",query(l,r,1,n,1).a[1][0]);
155         }
156         else
157         {
158             scanf("%d %d %d",&l,&r,&v);
159             mat t;t.init(2,2);t.a[0][0]=0;t.a[0][1]=1;t.a[1][1]=1;t.a[1][0]=1;
160             t=t^v;
161             update(l,r,t,1,n,1);
162         }
163 
164     }
165     return 0;
166 }
原文地址:https://www.cnblogs.com/lhclqslove/p/9372264.html