hdu 5068
2015-08-07 18:07
239 查看
一道好题~
用矩阵代替DP方程。
对于每个房间构造一个矩阵mat,mat[i][j] = 1 或 0 表示 ii 到 jj 是否能到达。
然后线段树每个结点维护区间区间矩阵乘法的结果
对于询问操作用矩阵乘法合并区间即可。
用矩阵代替DP方程。
对于每个房间构造一个矩阵mat,mat[i][j] = 1 或 0 表示 ii 到 jj 是否能到达。
然后线段树每个结点维护区间区间矩阵乘法的结果
对于询问操作用矩阵乘法合并区间即可。
#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; }
相关文章推荐
- Dev GridView RowCellClick活动MouseDown事件
- hdu 5068 分类: hdu 2015-08-07 18:07 7人阅读 评论(0) 收藏
- 如何抓微信的请求
- KMP中求解next值的模板
- 在Linux系统中查看进程及杀死僵尸进程的方法
- 事务隔离级别
- QQ表情
- linux 同步时间 调试core内核
- C#实现清除IE浏览器缓存的方法
- 数字旋转方阵
- 报错:require_once cannot allocate memory----php,以前自己弄的稍微有点特殊的开发环境
- 关于Entity Framework采用DB First模式创建后的实体批量修改相关属性技巧
- 解决安卓TextView高度和textSize大小不一致问题
- 安装phpstorm对yii的支持(YiiStorm)
- osg 反走样学习
- 我的CSDN第一天
- 233 - Number of Digit One
- 一张图记住Linux系统常用诊断工具
- 古代饮食
- 数组A包含0到n的所有整数,但其中缺了一个,且数组A里的整数都是用二进制形式存储,求这个缺失的整数