• CF718C Sasha and Array(线段树维护矩阵)


    题解

    (不会矩阵加速的先去学矩阵加速)

    反正我想不到线段树维护矩阵。我太菜了。

    我们在线段树上维护一个区间的斐波那契的列矩阵的和。

    然后询问时提取每个符合题意列矩阵的答案项(不是列矩阵存了两项吗,一个是当前项,一个是用来递推的)

    因为矩阵乘有结合律所以区间加这个操作就直接区间乘变换矩阵的x次方就行。

    然后记得开long long

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 const long long mod=1e9+7;
      8 const long long N=100100;
      9 long long n,m;
     10 struct jz{
     11     long long a[3][3];
     12 }e,h,be,f[N],ma;
     13 struct tree{
     14     long long l,r;
     15     jz sum,lazy;
     16 }tr[N*5];
     17 jz jzc(jz a,jz b,jz c){
     18     for(long long i=1;i<=2;i++)
     19         for(long long j=1;j<=2;j++)
     20             for(long long k=1;k<=2;k++){
     21                 c.a[i][j]+=a.a[i][k]*b.a[k][j];
     22                 c.a[i][j]%=mod; 
     23             }
     24     return c;
     25 }
     26 jz ksm(long long b,jz x){
     27     jz ans;
     28     ans=ma;
     29     while(b){
     30         if(b&1){
     31             ans=jzc(ans,x,h);
     32         }
     33         b>>=1;
     34         x=jzc(x,x,h);
     35     }
     36     return ans;
     37 }
     38 void update(long long now){
     39     tr[now].sum.a[1][1]=(tr[now*2].sum.a[1][1]+tr[now*2+1].sum.a[1][1])%mod;
     40     tr[now].sum.a[1][2]=(tr[now*2].sum.a[1][2]+tr[now*2+1].sum.a[1][2])%mod;
     41 }
     42 void build(long long l,long long r,long long now){
     43     tr[now].l=l;tr[now].r=r;tr[now].lazy=ma;
     44     if(l==r){
     45         tr[now].sum=f[l];
     46         return;
     47     }
     48     long long mid=(l+r)>>1;
     49     build(l,mid,now*2);
     50     build(mid+1,r,now*2+1);
     51     update(now);
     52 }
     53 bool pd(jz a,jz b){
     54     for(long long i=1;i<=2;i++)
     55         for(long long j=1;j<=2;j++)
     56             if(a.a[i][j]!=b.a[i][j])return false;
     57     return true;
     58 }
     59 void pushdown(long long now){
     60     if(pd(tr[now].lazy,ma))return;
     61     tr[now*2].sum=jzc(tr[now*2].sum,tr[now].lazy,h);
     62     tr[now*2+1].sum=jzc(tr[now*2+1].sum,tr[now].lazy,h);
     63     tr[now*2].lazy=jzc(tr[now*2].lazy,tr[now].lazy,h);
     64     tr[now*2+1].lazy=jzc(tr[now*2+1].lazy,tr[now].lazy,h);
     65     tr[now].lazy=ma;
     66 }
     67 void add(long long l,long long r,long long now,jz x){
     68     pushdown(now);
     69     if(tr[now].l==l&&tr[now].r==r){
     70         tr[now].sum=jzc(tr[now].sum,x,h);
     71         tr[now].lazy=x;
     72         return;
     73     }
     74     long long mid=(tr[now].l+tr[now].r)>>1;
     75     if(l>mid)add(l,r,now*2+1,x);
     76     else if(r<=mid)add(l,r,now*2,x);
     77     else{
     78         add(l,mid,now*2,x);
     79         add(mid+1,r,now*2+1,x); 
     80     }
     81     update(now);
     82 }
     83 long long query(long long l,long long r,long long now){
     84     pushdown(now);
     85     if(tr[now].l==l&&tr[now].r==r){
     86         return tr[now].sum.a[1][2];
     87     }
     88     long long mid=(tr[now].l+tr[now].r)>>1;
     89     if(l>mid)return query(l,r,now*2+1);
     90     else if(r<=mid)return query(l,r,now*2);
     91     else return (query(l,mid,now*2)+query(mid+1,r,now*2+1))%mod;
     92 }
     93 int main(){
     94     scanf("%lld%lld",&n,&m);
     95     e.a[1][1]=0;e.a[1][2]=e.a[2][1]=e.a[2][2]=1;
     96     be.a[1][1]=0;be.a[1][2]=1;
     97     for(long long i=1;i<=2;i++)
     98         for(long long j=1;j<=2;j++)
     99             if(i==j)ma.a[i][j]=1;
    100             else ma.a[i][j]=0;
    101     for(long long i=1;i<=n;i++){
    102         long long x;
    103         scanf("%lld",&x);
    104         if(x==1)f[i]=be;
    105         else f[i]=jzc(be,ksm(x-1,e),h); 
    106     }
    107     build(1,n,1);
    108     for(long long i=1;i<=m;i++){
    109         long long k;
    110         scanf("%lld",&k);
    111         if(k==1){
    112             long long l,r,x;
    113             scanf("%lld%lld%lld",&l,&r,&x);
    114             add(l,r,1,ksm(x,e));
    115         }
    116         else{
    117             long long l,r;
    118             scanf("%lld%lld",&l,&r);
    119             printf("%lld
    ",query(l,r,1));
    120         }
    121     }
    122     return 0;
    123 }
    View Code
  • 相关阅读:
    构造函数与其他类方法的区别
    将博客搬至51CTO
    易错点
    c++类构造函数详解
    将博客搬至CSDN
    实数,有理数,无理数,自然数,整数的概念分别是什么?
    code for qint function
    spline和Pchips的不同(matlab)
    Pseudocode MD5 CODE
    git基础介绍
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9403450.html
Copyright © 2020-2023  润新知