线段树 + 矩阵 --- ZOJ 3772 Calculate the Function

 Calculate the Function

Problem's Link:   http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3772


 

Mean: 

 

analyse:

简单的线段树维护矩阵。

矩阵乘法的结合律(a * b * c == a * (b * c)),注意矩阵乘法不满足分配率(a *b != b * a)。

 

令 M[x] = [1 A[x]]
              [1     0 ] ,
那么有 [ F[R] ] = M[R] * M[R-1] * ... * M[L+2] * [F[L+1]]
          [F[R-1]]                                                   [ F[L] ] 

 

线段树节点维护上边等式右边前n - 1项的乘值(假设等式右边有n项)。每次询问O(log(n))。

 

Time complexity: O(n*logn)

 

Source code: 

 

线段树 + 矩阵 --- ZOJ 3772 Calculate the Function
/*

* this code is made by crazyacking

* Verdict: Accepted

* Submission Date: 2015-05-25-20.57

* Time: 0MS

* Memory: 137KB

*/

#include <queue>

#include <cstdio>

#include <set>

#include <string>

#include <stack>

#include <cmath>

#include <climits>

#include <map>

#include <cstdlib>

#include <iostream>

#include <vector>

#include <algorithm>

#include <cstring>

#define  LL long long

#define  ULL unsigned long long

using namespace std;



const int MAXN = 100100;

const int MOD = 1000000007;

struct Mat

{

    long long m[2][2];

    Mat()

    {

            memset(m, 0, sizeof(m));

    }

    Mat operator * (const Mat &b)

    {

        Mat temp;

        for(int i = 0; i < 2; i++)

            for(int j = 0; j < 2; j++)

                for(int k = 0; k < 2; k++)

                    temp.m[i][j] = ((m[i][k] * b.m[k][j]) + temp.m[i][j]) % MOD;

        return temp;

    }

};



struct Node

{

    int l, r;

    Mat mat;

};

Node node[MAXN << 2];

int a[MAXN];



void Build(int rt, int l, int r)

{

    int m;

    node[rt].l = l;

    node[rt].r = r;

    if(l == r)

    {

        node[rt].mat.m[0][0] = 1;

        node[rt].mat.m[0][1] = a[l];

        node[rt].mat.m[1][0] = 1;

        node[rt].mat.m[1][1] = 0;

    }

    else

    {

        m = (l + r) >> 1;

        Build(rt << 1, l, m);

        Build(rt << 1 | 1, m + 1, r);

        node[rt].mat = node[rt << 1 | 1].mat * node[rt << 1].mat;//注意顺序

    }



}

Mat Query(int rt, int ql, int qr)

{

    int m;

    if(ql == node[rt].l && node[rt].r == qr)

        return node[rt].mat;

    else

    {

        m = (node[rt].l + node[rt].r) >> 1;

        if(qr <= m)

            return Query(rt << 1, ql, qr);

        else if(ql > m)

            return Query(rt << 1 | 1, ql, qr);

        else

            return Query(rt << 1 | 1, m + 1, qr) * Query(rt << 1, ql, m);//注意顺序

    }

}

int T, n, m, ql, qr;



int main()

{

    scanf("%d", &T);

    while(T--)

    {

        Mat res, f;

        scanf("%d%d",&n, &m);

        for(int i = 1; i <= n; i++)

            scanf("%d", &a[i]);

        Build(1, 1, n);

        for(int i = 1; i<= m; i++)

        {

            scanf("%d%d", &ql, &qr);

            if(qr - ql >= 2)

            {

                f.m[0][0] = a[ql + 1];

                f.m[1][0] = a[ql];

                res = Query(1, ql + 2, qr) * f;

                printf("%d\n", res.m[0][0]);

            }

            else

                printf("%d\n", a[qr]);

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(function)