题解CF718C【サーシャとアレイ】

トピックリンク

この問題は、推奨に加えて、良いタイトルのツリーライン行列を維持することであると言っている\(LibreOJ \)に良い質問「THUSCH 2017」偉大な魔術師は、セグメントツリーの行列を維持することができます

ソリューション[CF718C]サーシャと配列

トピックの効果:あなたはどのような二つのことをサポートするために、列の数を維持してください:

\(1 \) 間隔\([L、R] \ ) プラス内の数\(X \)

\(2 \) 需要\(\ sum_ {I = L} ^ {R&LT} F(A_ {I})\) \(F(x)が\)フィボナッチ列表す\(Xを)\アイテム

実践:今すぐデータ範囲に到達したこと\(N、M \の当量の1E5 \) レベル、そして我々は考慮する必要があります\(O(nlogn)\)アルゴリズムのレベルを

私たちがしているかを思い出してください(O(LOGN)\)\卓越した複雑さの要件フィボナッチ列を。行列の乗算、右?

我々は、マトリックス設定(\ Orgin = \ {bmatrix} 0を開始&1つの\終了{bmatrix})\を、転送行列(W = \ {bmatrix開始\ \} 1&1 \\ 1&0 \端{bmatrixを})

それは明らかである(F(X)= orgin \ ; * \; \ ^ X \ w)の、すなわち表現する\(F(X)\)を乗じた行列\(^ k個の\ w)を得るために、\(Fを( X + K)\)

それは、私たちは、オペレーティング・解決していることは明らかである\を(1 \) A

操作のために\(2 \) 我々は唯一の区間行列を維持し、する必要があります。正しさを明らかに、行列が連想されそうです。

\(\ sum_ {i = L} ^ RW * A_ {I}はW = * \ sum_ {i = L} ^ {R} \)

したがって、この問題は、セクションのタイトルをまとめたテンプレートの範囲を取ることです、開くように注意を払う(;長い\ \ロング)\をのような

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn = 100100;
const int mod = 1e9 + 7;
struct matrix{//矩阵模板
    ll val[4][4];
    int x,y;
    matrix operator * (const matrix &rhs)const{
        matrix ret;
        ret.x = x;
        ret.y = rhs.y;
        for(int i = 1;i <= ret.x;i++)
            for(int j = 1;j <= ret.y;j++){
                ret.val[i][j] = 0;
                for(int k = 1;k <= y;k++)
                    ret.val[i][j] += val[i][k] * rhs.val[k][j],ret.val[i][j] %= mod;
            }
        return ret;
    }
    matrix operator + (const matrix &rhs)const{
        matrix ret;
        ret.x = rhs.x;
        ret.y = rhs.y;
        for(int i = 1;i <= ret.x;i++)
            for(int j = 1;j <= ret.y;j++)
                ret.val[i][j] = (val[i][j] + rhs.val[i][j]) % mod;
        return ret;
    }
    inline void print(){
        for(int i = 1;i <= x;i++){
            for(int j = 1;j <= y;j++)
                printf("%lld ",val[i][j]);
            printf("\n");
        }
        printf("\n");
    }
}orgin,w,unit;
inline void init(){//初始化,orgin上文已经提到,w为转移矩阵,unit为单位矩阵
    orgin.x = 1;
    orgin.y = 2;
    orgin.val[1][1] = 0;
    orgin.val[1][2] = 1;
    w.x = w.y = 2;
    w.val[1][1] = 1;
    w.val[1][2] = 1;
    w.val[2][1] = 1;
    w.val[2][2] = 0;
    unit.x = unit.y = 2;
    unit.val[1][1] = 1;
    unit.val[2][2] = 1;
}
namespace ST{//线段树模板
    struct Node{
        int l,r;
        matrix mark,val;
    }tree[maxn << 2];
    #define lson (root << 1)
    #define rson (root << 1 | 1)
    inline void maintain(int root){
        tree[root].val = tree[lson].val + tree[rson].val;
    }
    inline void pushdown(int root){
        tree[lson].val = tree[lson].val * tree[root].mark;
        tree[lson].mark = tree[lson].mark * tree[root].mark;
        tree[rson].val = tree[rson].val * tree[root].mark;
        tree[rson].mark = tree[rson].mark * tree[root].mark;
        tree[root].mark = unit;
    }
    inline void build(int a,int b,int root = 1){
        tree[root].l = a;
        tree[root].r = b;
        tree[root].mark = unit;
        if(a == b){
            tree[root].val = orgin;
            return;
        }
        int mid = (tree[root].l + tree[root].r) >> 1;
        build(a,mid,lson);
        build(mid + 1,b,rson);
        maintain(root);
    }
    inline ll query(int a,int b,int root = 1){
        if(a <= tree[root].l && b >= tree[root].r)return tree[root].val.val[1][1];
        pushdown(root);
        ll ret = 0;
        int mid = (tree[root].l + tree[root].r) >> 1;
        if(a <= mid)ret += query(a,b,lson),ret %= mod;
        if(b >= mid + 1)ret += query(a,b,rson),ret %= mod;
        return ret;
    }
    inline void modify(int a,int b,const matrix val,int root = 1){
        if(a <= tree[root].l && b >= tree[root].r){
            tree[root].val = tree[root].val * val;
            tree[root].mark = tree[root].mark * val;
            return;
        }
        pushdown(root);
        int mid = (tree[root].l + tree[root].r) >> 1;
        if(a <= mid)modify(a,b,val,lson);
        if(b >= mid + 1)modify(a,b,val,rson);
        maintain(root);
    }
    #undef lson
    #undef rson
}
inline matrix power(const matrix &a,int b){//快速幂
    matrix ret = unit,base = a;
    while(b){
        if(b & 1)ret = ret * base;
        base = base * base;
        b >>= 1;
    }
    return ret;
}
int n,m;
int main(){
#ifdef LOCAL
    freopen("fafa.in","r",stdin);
#endif
    init();
    scanf("%d %d",&n,&m);
    ST::build(1,n);
    for(int x,i = 1;i <= n;i++)//实在没想到啥更好的初始化办法了,我还是tcl
        scanf("%d",&x),ST::modify(i,i,power(w,x));
    for(int i = 1;i <= m;i++){
        int opt,l,r,x;
        scanf("%d %d %d",&opt,&l,&r);
        if(opt == 1)scanf("%d",&x),ST::modify(l,r,power(w,x));
        else printf("%lld\n",ST::query(l,r));
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/colazcy/p/11514996.html