hdu 5068 分类: hdu 2015-08-07 18:07 7人阅读 评论(0) 收藏


一道好题~


用矩阵代替DP方程。

对于每个房间构造一个矩阵mat,mat[i][j] = 1 或 0 表示 ij 是否能到达。


然后线段树每个结点维护区间区间矩阵乘法的结果

对于询问操作用矩阵乘法合并区间即可。


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <vector>
#include <utility>
#include <stack>
#include <queue>
#include <iostream>
#include <algorithm>

template<class Num>void read(Num &x)
{
    char c; int flag = 1;
    while((c = getchar()) < '0' || c > '9')
        if(c == '-') flag *= -1;
    x = c - '0';
    while((c = getchar()) >= '0' && c <= '9')
        x = (x<<3) + (x<<1) + (c-'0');
    x *= flag;
    return;
}
template<class Num>void write(Num x)
{
    if(x < 0) putchar('-'), x = -x;
    static char s[20];int sl = 0;
    while(x) s[sl++] = x%10 + '0',x /= 10;
    if(!sl) {putchar('0');return;}
    while(sl) putchar(s[--sl]);
}
const int maxn = 50005, Mod = 1e9 + 7;

struct Matrix
{
    long long a[2][2];
}emp, tree[maxn<<2];

Matrix operator *(const Matrix &A, const Matrix &B)
{
    Matrix ret = emp;

    for(int i = 0; i < 2; i++)
        for(int j = 0; j < 2; j++)
            for(int k = 0; k < 2; k++)
                ret.a[i][j] = (ret.a[i][j] + A.a[i][k]*B.a[k][j])%Mod;

    return ret;        
}

#define L(x) ((x)<<1)
#define R(x) ((x)<<1|1)

void update(int x)
{
    tree[x] = tree[L(x)]*tree[R(x)];
}
void build(int ll,int rr,int si)
{
    if(ll == rr)
    {
        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 2; j++)
                tree[si].a[i][j] = 1;
        return;        
    }
    int mid = (ll + rr)>>1;

    build(ll, mid, L(si));
    build(mid + 1, rr, R(si));

    update(si);
}
void change(int k,int x,int y,int ll,int rr,int si)
{
    if(ll == rr)
    {
        tree[si].a[x][y] ^= 1;
        return;
    }

    int mid = (ll + rr)>>1;

    if(k <= mid) change(k, x, y, ll, mid, L(si));
    else change(k, x, y, mid + 1, rr, R(si));

    update(si);
}
Matrix query(int l,int r,int ll,int rr,int si)
{    
    if(ll == l && rr == r) return tree[si];

    int mid = (ll + rr)>>1;

    if(mid < l)    return query(l, r, mid + 1, rr, R(si));
    if(r <= mid) return query(l, r, ll, mid, L(si));
    return query(l, mid, ll, mid, L(si))*query(mid + 1, r, mid + 1, rr, R(si));
}
#undef L
#undef R

long long calcu(Matrix P)
{
    return (P.a[0][0] + P.a[0][1] + P.a[1][0] + P.a[1][1])%Mod;
}


int main()
{
    int n, m;

#ifndef ONLINE_JUDGE
    freopen("hdu5068.in","r",stdin);
    freopen("hdu5068.out","w",stdout);
#endif

    while(scanf("%d%d",&n,&m) != EOF)
    {
        build(1, n - 1, 1);

        while(m --)
        {
            int op, x, y, z;

            read(op), read(x), read(y);

            if(op)
                read(z), change(x, y - 1, z - 1, 1, n - 1, 1);
            else
                write(calcu(query(x, y - 1, 1, n - 1, 1))), puts("");
        }
    }

#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
#endif
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

posted @ 2015-08-07 18:07  <Dash>  阅读(153)  评论(0编辑  收藏  举报