zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    洛谷 P1313 计算系数
    洛谷 P1088 火星人
    洛谷 P1049 装箱问题
    P5016 龙虎斗
    洛谷P1208
    求lca
    没有上司的舞会
    最短路spfa
    懒羊羊找朋友
    简单的图论问题之单源最短路dijkstra算法
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9886376.html
Copyright © 2011-2022 走看看