hdu 5068 分类: hdu 2015-08-07 18:07 7人阅读 评论(0) 收藏
一道好题~
用矩阵代替DP方程。
对于每个房间构造一个矩阵mat,mat[i][j] = 1 或 0 表示
然后线段树每个结点维护区间区间矩阵乘法的结果
对于询问操作用矩阵乘法合并区间即可。
#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;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。