HDU 5068 Harry And Math Teacher (矩陣處理,線段樹)

題目:LINK

該層的兩個門到下一層的兩個門的開關狀態可以表示成一個2*2的矩陣1表示開0表示關,每次狀態的改變就是對應位置0->1, 1->0,對於查詢[a,b], 只要求出a到b-1的矩陣的乘積就可以了。
由於有改變和多次查詢,所以可以用線段樹進行維護,單點更新,區間查詢。


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std; 
#define INF 1000000000
typedef __int64 LL; 
#define N 3
const LL mod = 1000000007; 
#define M 50005

int n, m; 
struct node {
    LL mat[N][N]; 
};
node S[M<<2]; 

node mul(node a, node b) {
    node ret; 
    memset(ret.mat, 0, sizeof(ret.mat)); 
    for(int k = 1; k <= 2; k++) {
        for(int i = 1; i <= 2; i++) {
            for(int j = 1; j <= 2; j++) {
                ret.mat[i][j] += a.mat[i][k] * b.mat[k][j]; 
                ret.mat[i][j] %= mod; 
            }
        }
    }
    return ret; 
}
void pushup(int rt) {
    S[rt] = mul(S[rt<<1], S[rt<<1|1]); 
}
void build(int l, int r, int rt) {
    if(l == r) {
        S[rt].mat[1][1] = S[rt].mat[1][2] = S[rt].mat[2][1] = S[rt].mat[2][2] = 1; 
        return ; 
    }
    int m = (l+r)>>1; 
    build(l, m, rt<<1); 
    build(m+1, r, rt<<1|1); 
    pushup(rt); 
}
node query(int L,int R,int l, int r, int rt) {
    if(L<=l && r<=R) {
        return S[rt]; 
    }
    int m = (l+r)>>1; 
    node ret; 
    ret.mat[1][1] = ret.mat[2][2] = 1; 
    ret.mat[1][2] = ret.mat[2][1] = 0; 
    if(L <= m) ret = mul(ret, query(L, R, l, m, rt<<1)); 
    if(R > m) ret = mul(ret, query(L, R, m+1, r, rt<<1|1)); 
    return ret; 
}
void updata(int a, int b, int c, int l, int r, int rt) {
    if(l == r) {
        S[rt].mat[b][c] = 1 - S[rt].mat[b][c];
        return ; 
    }
    int m = (l+r)>>1; 
    if(a <= m) updata(a, b, c, l, m, rt<<1); 
    else updata(a, b, c, m+1, r, rt<<1|1); 
    pushup(rt); 
}
int main() {
    while(scanf("%d%d", &n, &m) != EOF) {
        build(1, n, 1); 
        for(int i = 1; i <= m; i++) {
            int tmp; 
            scanf("%d", &tmp); 
            if(tmp == 0) {
                int a, b; 
                scanf("%d%d", &a, &b); 
                node ans = query(a, b-1,1, n, 1); 
                LL out = 0; 
                for(int q = 1; q <= 2; q++) {
                    for(int j = 1; j <= 2; j ++) {
                        out += ans.mat[q][j]; 
                        out %= mod; 
                    }
                }
                printf("%I64d\n", out); 
            }
            else {
                int a, b, c; 
                scanf("%d%d%d", &a, &b, &c); 
                updata(a, b, c, 1, n, 1); 
            }
        }
    }
    return 0; 
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章