hdu 5068

来源:互联网 发布:一个人根本做不起淘宝 编辑:程序博客网 时间:2024/06/05 15:35

一道好题~


用矩阵代替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 Rlong 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;}
0 0