• 2020牛客寒假算法基础集训营2【J】-求函数(线段树维护矩阵)


    题目链接:https://ac.nowcoder.com/acm/contest/3003/J

    根据条件构造下列矩阵

    根据题意不难想到用线段树维护。

    注意矩阵乘法的顺序,不遵循交换律,合并区间时右子树在前。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int mod=1e9+7,maxn=2e5+10;
     5 inline int lx(signed x){return x<<1;}
     6 inline int rx(signed x){return x<<1|1;}
     7 int kk[maxn],bb[maxn];
     8 struct mat{
     9     ll a11,a12,a21,a22;
    10     mat(){}
    11     mat(ll a,ll b,ll c,ll d){a11=a,a12=b,a21=c,a22=d;}
    12     friend mat operator *(mat a,mat b){
    13         return mat(
    14                 (a.a11*b.a11+a.a12*b.a21)%mod,
    15                 (a.a11*b.a12+a.a12*b.a22)%mod,
    16                 (a.a21*b.a11+a.a22*b.a21)%mod,
    17                 (a.a21*b.a21+a.a22*b.a22)%mod
    18                 );
    19     }
    20 };
    21 struct Node{
    22     int l,r;
    23     mat val;
    24 }tree[maxn<<2];
    25 inline void pushup(int root){tree[root].val=tree[rx(root)].val*tree[lx(root)].val;}
    26 void build(int root,int l,int r){
    27     tree[root].l=l,tree[root].r=r;
    28     if(l==r){
    29         tree[root].val=mat(kk[l],bb[l],0,1);
    30         return;
    31     }
    32     int mid=(l+r)>>1;
    33     build(lx(root),l,mid);
    34     build(rx(root),mid+1,r);
    35     pushup(root);
    36 }
    37 void update(int pos,mat ma,int root){
    38     if(tree[root].l==tree[root].r){
    39         tree[root].val=ma;
    40         return;
    41     }
    42     int mid=(tree[root].l+tree[root].r)>>1;
    43     if(pos<=mid)
    44         update(pos,ma,lx(root));
    45     else
    46         update(pos,ma,rx(root));
    47     pushup(root);
    48 }
    49 mat query(int l,int r,int root){
    50     assert(r>=l);
    51     int mid=(tree[root].l+tree[root].r)>>1;
    52     if(tree[root].l==l&&tree[root].r==r)return tree[root].val;
    53     if(mid>=r)return query(l,r,lx(root));
    54     else if (mid<l)return query(l,r,rx(root));
    55     else return query(mid+1,r,rx(root))*query(l,mid,lx(root));
    56 }
    57 int main(){
    58     int n,m;
    59     scanf("%d %d",&n,&m);
    60     for(int i=1;i<=n;i++)
    61         scanf("%d",&kk[i]);
    62     for(int i=1;i<=n;i++)
    63         scanf("%d",&bb[i]);
    64     build(1,1,n);
    65     while(m--){
    66         int op;
    67         cin>>op;
    68         if(op==1){
    69             int i,k,b;
    70             scanf("%d%d%d",&i,&k,&b);
    71             update(i,mat(k,b,0,1),1);
    72         }else{
    73             int l,r;
    74             scanf("%d %d",&l,&r);
    75             mat res=query(l,r,1);
    76             printf("%lld
    ",(res.a11+res.a12)%mod);
    77         }
    78     }
    79     return 0;
    80 }

    ----------------------------------------------分割线---------------------------------------------------------------------------------------

    另附官方题解

     标程很短就不贴了,以我的脑子现场一时半会儿应该是推不出来的QAQ

  • 相关阅读:
    ajax是什么? ajax的交互模型? 同步和异步的区别? 如何解决跨域问题?
    集锦 比较好
    集锦
    伊甸园日历游戏
    晴天小猪历险记之Hill
    求无向图最小环算法
    旅行商简化版
    十字绣
    破坏石油运输系统问题
    强墙
  • 原文地址:https://www.cnblogs.com/charles1999/p/12270227.html
Copyright © 2020-2023  润新知