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

传送门

解题思路:

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

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

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

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

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

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

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

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

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

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

  1 #include
  2 #include
  3 #include
  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\n",(query(1,n,l,r,1).s[0][0]%mod+mod)%mod);
184         }
185     }
186     return 0;
187 }

 

转载于:https://www.cnblogs.com/blog-Dr-J/p/9886376.html

你可能感兴趣的:(Codeforces 718C. Sasha and Array(线段树))