HDU 5068 Harry And Math Teacher 线段树维护矩阵乘积
来源:互联网 发布:荣威rx5发动机 知乎 编辑:程序博客网 时间:2024/06/02 00:24
题意:相邻的两层楼之间有两个门,每个门内都有一个楼梯,分别通向上一层的两扇门。但是,门内的楼梯会转换状态。所有楼梯起始都是通的。在状态转后后,会从通变成不通,反之也可以。如果楼梯是不通的,那就不能从该楼梯到上一层。有以下两种操作:1.修改X层第Y个门通向上一层的第Z个门的楼梯的状态。2.查询从第X层到第Y层的所有的方案数。
思路:因为查询的是方案数,我们想到了DP。但是,题目中的是动态修改动态查询,怎么办呢?因为是线性递推,我们可以利用矩阵来计算方案数。
同时,因为矩阵满足结合律,我们就可以利用线段树来保存成段的矩阵乘积。而修改就是单点修改了。
注意:虽然题目中明确要求用取模运算,但是在计算的过程中还是会爆int的,所以要用long long.
代码如下:
#include <cstdio>#include <algorithm>#include <cstring>using namespace std;typedef long long ll;const ll MOD = 1000000007;const int MAX = 50010;struct Matrix{ ll a[2][2]; Matrix(){memset(a,0,sizeof(a));} Matrix operator * (const Matrix & A) const{ Matrix C; for(int i = 0; i < 2; ++i) for(int j = 0; j < 2; ++j) for(int k = 0; k < 2; ++k) C.a[i][j] = (C.a[i][j] + a[i][k] * A.a[k][j]) % MOD; return C; }};#define lson(o) (o<<1)#define rson(o) ((o<<1)|1)struct yy{ Matrix m; int l,r;} node[MAX<<3];void pushup(int o){ node[o].m = node[lson(o)].m * node[rson(o)].m;}void build(int l, int r, int o){ node[o].l = l; node[o].r = r; if(l == r){ for(int i = 0; i < 2; ++i) for(int j = 0; j < 2; ++j) node[o].m.a[i][j] = 1; return; } int mid = (l + r) >>1; build(l,mid,lson(o)); build(mid+1,r,rson(o)); pushup(o);}int x,y,z;void update(int x,int o){ if(node[o].l == node[o].r){ node[o].m.a[y][z] ^= 1; return; } int mid = (node[o].l + node[o].r) >> 1; if(x <= mid) update(x,lson(o)); else update(x,rson(o)); pushup(o);}Matrix query(int L,int R,int o){ if(L <= node[o].l && R >= node[o].r) return node[o].m; Matrix ans; ans.a[0][0] = ans.a[1][1] = 1; int mid = (node[o].l + node[o].r) >> 1; if(L <= mid) ans = ans * query(L,R,lson(o)); if(R > mid) ans = ans * query(L,R,rson(o)); return ans;}int main(void){ //freopen("in","r",stdin); int N,M; while(~scanf("%d%d", &N,&M)){ build(1,N-1,1); for(int i = 0; i < M; ++i){ int Q; scanf("%d", &Q); if(Q==1){ scanf("%d %d %d", &x,&y,&z); y--,z--; update(x,1); } else{ scanf("%d %d", &x,&y); Matrix ret = query(x,y-1,1); ll ans = 0; for(int i = 0; i < 2; ++i) for(int j = 0; j < 2; ++j) ans = (ans + ret.a[i][j]) % MOD; printf("%I64d\n",ans); } } } return 0;}
0 0
- HDU 5068 Harry And Math Teacher 线段树维护矩阵乘积
- HDU 5068 Harry And Math Teacher (矩阵处理,线段树)
- hdu 5068 Harry And Math Teacher 线段树
- HDU-5068-Harry And Math Teacher(线段树)
- hdu 5068 Harry And Math Teacher ( 线段树+矩阵乘法 )
- 【线段树】 HDOJ 5068 Harry And Math Teacher
- HDU 5068 Harry And Math Teacher
- hdu-5068 Harry And Math Teacher
- BestCoder Round #14 03 Harry And Math Teacher (线段树)
- hdu 5068 线段树维护矩阵乘积
- hdu 5068 Harry And Math Teacher(BestCoder Round #14)
- 【HDU5068】Harry And Math Teacher
- HDU 5069 Harry And Biological Teacher(fail树+线段树优化)
- HDU 5069 Harry And Biological Teacher AC自动机 + 线段树优化 (BestCoder Round 14 D)
- HDU 5066 Harry And Physical Teacher 物理
- hdu 5066 Harry And Physical Teacher(数学)
- HDU 5066 Harry And Physical Teacher
- HDU 5066Harry And Physical Teacher(数学)
- C#知识
- canvas制作时钟
- Search in Rotated Sorted Array
- 目标黑马,我的自学之路:第十三章 设计模式
- eclipse 无法启动AVD,出现Starting emulator for AVD '' PANIC: Could not open: 错误提示的解决办法
- HDU 5068 Harry And Math Teacher 线段树维护矩阵乘积
- const int& a = 100; 这种引用虽然可以, 但要少用或者不用
- Window 错误码介绍
- 编程之美3.2 电话号码对应英语字母
- UVA—11464
- Unicode字符处理
- WireShark过滤TCP及端口
- GDB中应该知道的几个调试方法
- 进程通信linux