ZOJ 3772 Calculate the Function(线段树+矩阵)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5235

题意:

题意很好懂 就是

给定一个数列  a1,a2,...,an 

对于一个递推式 F[L]=a[L],F[L+1]=a[L+1],F[X] = F[X-1]+F[X-2]*aX,

然后给定m个询问,每次给定L,R, 求F(R);

对于这个递推式 每一项我们可以得到一个状态转移矩阵 

| F[x]    |   | 1   ,    a[x] |

|           |= |                  |

| F[x-1] |   | 1   ,      0   |

所以我们可以用线段树维护这个矩阵,值得因为矩阵的乘法满足结合律不满足交换律

因此我们在维护的时候需要注意一下 F[R] = (Mr*Mr-1*.....*Ml+2)*A;要注意维护的时候

要保证好这个顺序。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#define PB push_back
#define MP make_pair
#define REP(i,n) for(int i=0;i<(n);++i)
#define FOR(i,l,h) for(int i=(l);i<=(h);++i)
#define DWN(i,h,l) for(int i=(h);i>=(l);--i)
#define IFOR(i,h,l,v) for(int i=(h);i<=(l);i+=(v))
#define CLR(vis) memset(vis,0,sizeof(vis))
#define MST(vis,pos) memset(vis,pos,sizeof(vis))
#define MAX3(a,b,c) max(a,max(b,c))
#define MAX4(a,b,c,d) max(max(a,b),max(c,d))
#define MIN3(a,b,c) min(a,min(b,c))
#define MIN4(a,b,c,d) min(min(a,b),min(c,d))
#define PI acos(-1.0)
#define INF 1000000000
#define LINF 1000000000000000000LL
#define eps 1e-8
#define LL long long
#define lson(id) id<<1
#define rson(id) id<<1|1

using namespace std;

const LL mod = 1e9+7;
const int maxn = 1e5+10;

int a[maxn];

struct matrix{
    LL m[2][2];
    matrix(){CLR(m);}
    matrix operator *(const struct matrix &tmp){
        matrix ans;
        REP(i,2){
            REP(j,2){
                ans.m[i][j]=0;
                REP(k,2)
                    ans.m[i][j]=(ans.m[i][j]+m[i][k]*tmp.m[k][j])%mod;
            }
        }
        return ans;
    }
};

struct seg_tree{
    int l,r;
    matrix ans;
}t[maxn<<2];

void build(int id,int l,int r){
    t[id].l=l,t[id].r=r;
    if(l==r){
        t[id].ans.m[0][0]=1;
        t[id].ans.m[0][1]=a[l];
        t[id].ans.m[1][0]=1;
        t[id].ans.m[1][1]=0;
        //cout<<"*** "<<t[id].ans.m[0][1]<<endl;
        return;
    }
    int mid=(l+r)>>1;
    build(lson(id),l,mid);
    build(rson(id),mid+1,r);
    t[id].ans=t[rson(id)].ans*t[lson(id)].ans;
}
matrix query(int id,int l,int r){
    if(l==t[id].l&&r==t[id].r) return t[id].ans;
    int mid = (t[id].l+t[id].r)>>1;
    if(mid>=r) return query(lson(id),l,r);
    else if(mid<l) return query(rson(id),l,r);
    else return query(rson(id),mid+1,r)*query(lson(id),l,mid);
}

int main()
{
    int t,n,m,l,r;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        FOR(i,1,n) scanf("%d",&a[i]);
        build(1,1,n);
        REP(i,m){
            scanf("%d%d",&l,&r);
            if(r-l>=2){
                matrix tmp;
                tmp.m[0][0]=a[l+1];
                tmp.m[1][0]=a[l];
                matrix ans =query(1,l+2,r)*tmp;
                printf("%lld\n",ans.m[0][0]);
            }
            else
                printf("%d\n",a[r]);
        }
    }
    return 0;
}


 


 

你可能感兴趣的:(ZOJ 3772 Calculate the Function(线段树+矩阵))