Codeforces 718C. Sasha and Array(线段树)

Posted blog-dr-j

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 718C. Sasha and Array(线段树)相关的知识,希望对你有一定的参考价值。

传送门

解题思路:

这道题给了我们一个崭新的角度来看线段树。

我们常常使用的线段树是维护区间的函数的。

这里呢,提示我们线段树其实还可以维护递推。

美好的矩阵递推性质支持了这一功能。

或者说,对于递推项求和,可以使用线段树维护矩阵。

区间向前递推可以用懒惰标记记录递推矩阵。

区间的查询可以是子节点矩阵和。

这其实也是满足分配率的。

最后pushup,pushdown搞一搞就好了。

代码(闲来无事卡常码风突变)

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define lll spc<<1
  5 #define rrr spc<<1|1
  6 typedef unsigned long long lnt;
  7 typedef unsigned int ixt;
  8 const lnt mod=(lnt)(1e9+7);
  9 struct squ{
 10     lnt s[2][2];
 11     inline void res(void)
 12     {
 13         memset(s,0,sizeof(s));
 14         return ;
 15     }
 16     inline void O1(void)
 17     {
 18         for(register int i=0;i<2;i++)
 19             s[i][i]=1;
 20         return ;
 21     }
 22     inline squ friend operator + (const squ &a,const squ &b)
 23     {
 24         squ ans;
 25         for(register int i=0;i<2;i++)
 26         {
 27             for(register int j=0;j<2;j++)
 28             {
 29                 ans.s[i][j]=(a.s[i][j]+b.s[i][j])%mod;
 30             }
 31         }
 32         return ans;
 33     }
 34     inline squ friend operator * (const squ &a,const squ &b)
 35     {
 36         squ ans;
 37         for(register int i=0;i<2;i++)
 38         {
 39             for(register int j=0;j<2;j++)
 40             {
 41                 ans.s[i][j]=0;
 42                 for(register int k=0;k<2;k++)
 43                 {
 44                     ans.s[i][j]=(ans.s[i][j]+a.s[i][k]*b.s[k][j])%mod;
 45                 }
 46             }
 47         }
 48         return ans;
 49     }
 50     inline squ friend operator ^ (squ a,lnt b)
 51     {
 52         squ ans=a;
 53         b--;
 54         while(b)
 55         {
 56             if(b&1)
 57                 ans=ans*a;
 58             a=a*a;
 59             b=b/2;
 60         }
 61         return ans;
 62     }
 63 }sta,pro;
 64 struct trnt{
 65     squ sum;
 66     squ lzt;
 67     bool op;
 68 }tr[1000000];
 69 ixt n,m;
 70 ixt a[1000000];
 71 inline void read(ixt &ans)
 72 {
 73     ans=0;
 74     char ch=getchar();
 75     while(ch<0||ch>9)
 76         ch=getchar();
 77     while(ch>=0&&ch<=9)
 78         ans=ans*10+ch-0,ch=getchar();
 79     return ;
 80 }
 81 inline squ Fib(const lnt &x)
 82 {
 83     squ tmp=pro^x;
 84     return tmp*sta;
 85 }
 86 inline void pushup(const int &spc)
 87 {
 88     tr[spc].sum=tr[lll].sum+tr[rrr].sum;
 89     return ;
 90 }
 91 inline void add(const int &spc,const squ &v)
 92 {
 93     tr[spc].op=true;
 94     tr[spc].lzt=v*tr[spc].lzt;
 95     tr[spc].sum=v*tr[spc].sum;
 96     return ;
 97 }
 98 inline void pushdown(const int &spc)
 99 {
100     if(tr[spc].op)
101     {
102         add(lll,tr[spc].lzt);
103         add(rrr,tr[spc].lzt);
104         tr[spc].lzt.res();
105         tr[spc].lzt.O1();
106         tr[spc].op=0;
107     }
108     return ;
109 }
110 inline void build(const int &l,const int &r,const int &spc)
111 {
112     tr[spc].lzt.res();
113     tr[spc].lzt.O1();
114     if(l==r)
115     {
116         tr[spc].sum=Fib(a[l]);
117         return ;
118     }
119     int mid=(l+r)>>1;
120     build(l,mid,lll);
121     build(mid+1,r,rrr);
122     pushup(spc);
123     return ;
124 }
125 inline void update(const int &l,const int &r,const int &ll,const int &rr,const int &spc,const squ &v)
126 {
127     if(ll>r||l>rr)
128         return ;
129     if(ll<=l&&r<=rr)
130     {
131         add(spc,v);
132         return ;
133     }
134     int mid=(l+r)>>1;
135     pushdown(spc);
136     update(l,mid,ll,rr,lll,v);
137     update(mid+1,r,ll,rr,rrr,v);
138     pushup(spc);
139     return ;
140 }
141 inline squ query(const int &l,const int &r,const int &ll,const int &rr,const int &spc)
142 {
143     squ ans;
144     ans.res();
145     if(l>rr||ll>r)
146         return ans;
147     if(ll<=l&&r<=rr)
148         return tr[spc].sum;
149     int mid=(l+r)>>1;
150     pushdown(spc);
151     return query(l,mid,ll,rr,lll)+query(mid+1,r,ll,rr,rrr);
152 }
153 int main()
154 {
155     sta.s[0][0]=0;
156     sta.s[1][0]=1;
157     pro.s[0][0]=1;
158     pro.s[0][1]=1;
159     pro.s[1][0]=1;
160     read(n);
161     read(m);
162     for(register int i=1;i<=n;i++)
163         scanf("%d",&a[i]);
164     build(1,n,1);
165     while(m--)
166     {
167         ixt opt;
168         read(opt);
169         if(opt==1)
170         {
171             ixt l,r,x;
172             read(l);
173             read(r);
174             read(x);
175             if(!x)
176                 continue;
177             squ tmp=pro^x;
178             update(1,n,l,r,1,tmp);
179         }else{
180             ixt l,r;
181             read(l);
182             read(r);
183             printf("%I64u
",(query(1,n,l,r,1).s[0][0]%mod+mod)%mod);
184         }
185     }
186     return 0;
187 }

 

以上是关于Codeforces 718C. Sasha and Array(线段树)的主要内容,如果未能解决你的问题,请参考以下文章

codeforces CF718C Sasha and Array 线段树维护矩阵

CodeForces 718C Sasha and Array

718C Sasha and Array

Codeforces718 C. Sasha and Array(线段树维护矩阵,矩阵快速幂求斐波那契数列,矩阵乘法结合律)

题解 CF718C Sasha and Array

题解 CF718C Sasha and Array