题意:

n * m的矩阵,为0表示可以走,1不可以走。规定每走一步只能向下、向左、向右走。现给定两种操作:
一.1 x y表示翻转坐标(x,y)的0、1。
二.2 x y表示从(1,x)走到(n,y)有几种走法

思路:

假设\(dp[i][j]\)表示从下一层能到达(i,j)点的路径数,那么显然到达(i,j)的路径数为\(dp[i + 1][j]\)。
我们能很显然的得到转移方程\(dp[i][j] = \sum_{k = l}^r dp[i - 1][k]\),其中l~r为(i,j)下方能直接走到(i,j)的连续区间。
我们可以直接用矩阵维护这个转移方程:
\[ \left( \begin{matrix} dp[i][1] & dp[i][2] & dp[i][3] & \cdots & dp[i][m] \end{matrix} \right) * A_i= \left( \begin{matrix} dp[i + 1][1] & dp[i + 1][2] & dp[i + 1][3] & \cdots & dp[i + 1][m] \end{matrix} \right) \]
然后用线段树维护矩阵乘积即可
从(1,x)走到(n,y)只需把x位置置为1,然后乘以\(\prod_{i = 1}^n A_i\)

代码:

#include<cstdio>
#include<set>
#include<cmath>
#include<stack>
#include<vector>
#include<queue>
#include<cstring>
#include<string>
#include<sstream>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 50000 + 5;
const int INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
int n, m, q;
int mp[maxn][12];
char s[12];
struct Mat{ll s[12][12];void init_zero(){for(int i = 0; i < 12; i++)for(int j = 0; j < 12; j++)s[i][j] = 0;}
};
Mat pmul(Mat a, Mat b, int len){Mat c;c.init_zero();for(int i = 1; i <= len; i++){for(int j = 1; j <= len; j++){for(int k = 1; k <= len; k++){c.s[i][j] = (c.s[i][j] + a.s[i][k] * b.s[k][j]) % MOD;}}}return c;
}Mat mul[maxn << 2], a[maxn];
void pushup(int rt){mul[rt] = pmul(mul[rt << 1], mul[rt << 1 | 1], m);
}
void build(int l, int r, int rt){if(l == r){for(int i = 1; i <= m; i++)for(int j = 1; j <= m; j++)mul[rt].s[i][j] = a[l].s[i][j];return;}int m = (l + r) >> 1;build(l, m, rt << 1);build(m + 1, r, rt << 1 | 1);pushup(rt);
}
void update(int pos, int l, int r, Mat aa, int rt){if(l == r){for(int i = 1; i <= m; i++)for(int j = 1; j <= m; j++)mul[rt].s[i][j] = aa.s[i][j];return;}int m = (l + r) >> 1;if(pos <= m)update(pos, l, m, aa, rt << 1);elseupdate(pos, m + 1, r, aa, rt << 1 | 1);pushup(rt);
}
int main(){scanf("%d%d%d", &n, &m, &q);for(int i = 1; i <= n; i++){scanf("%s", s + 1);for(int j = 1; j <= m; j++){mp[i][j] = s[j] - '0';}}for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){int base;base = 1;for(int k = j; k >= 1; k--){if(mp[i][k] == 1) base = 0;a[i].s[k][j] = base;}base = 1;for(int k = j; k <= m; k++){if(mp[i][k] == 1) base = 0;a[i].s[k][j] = base;}}}//    for(int k = 1; k <= n; k++){
//        for(int i = 1; i <= m; i++){
//            for(int j = 1; j <= m; j++){
//                printf("%d ", a[k].s[i][j]);
//            }
//            puts("");
//        }
//        puts("*****");
//    }build(1, n, 1);while(q--){int ques, i, j;scanf("%d", &ques);scanf("%d%d", &i, &j);if(ques == 1){mp[i][j] = !mp[i][j];for(int j = 1; j <= m; j++){int base;base = 1;for(int k = j; k >= 1; k--){if(mp[i][k] == 1) base = 0;a[i].s[k][j] = base;}base = 1;for(int k = j; k <= m; k++){if(mp[i][k] == 1) base = 0;a[i].s[k][j] = base;}}update(i, 1, n, a[i], 1);}else{Mat ret;ret.init_zero();ret.s[1][i] = 1;ret = pmul(ret, mul[1], m);printf("%lld\n", ret.s[1][j]);}}return 0;
}
/*
2 6 1
0 0 0 1 0 0
1 0 1 0 1 0
*/

转载于:https://www.cnblogs.com/KirinSB/p/11232545.html

2019牛客多校第二场E MAZE(线段树 + 矩阵)题解相关推荐

  1. 2019 牛客多校第二场 4/10

    题会慢慢补完的,最近在帮别人上课,补题速度很慢,一边看ppt一边刷ppt的题还要补多校的,感觉有点应付不过来,不过以后会慢慢补完的(指整个暑假) A 这场出题人的英文水平真的搞事,不说了((( 这题起 ...

  2. 2019牛客多校第一场

    2019牛客多校第一场 题号 题目 知识点 A Monotonic Matrix B Symmetric Matrix C Fluorescent 2 D Two Graphs E Removal F ...

  3. 2019牛客多校第九场AThe power of Fibonacci(广义BM)

    2019牛客多校第九场AThe power of Fibonacci(广义BM) 题目大意 求斐波那契数列m次方的前n项和 解题思路 显然,斐波那契的m次方前缀和依然是线性递推,因此考虑用exBM求解 ...

  4. 牛客多校第二场补题(继续罚坐)

    牛客多校第二场(继续罚坐场) Draw Grids ZYT和LBC玩游戏,在4*4的矩阵中,从起点开始,每个人只能连一条直线,且只能在起点或者上一个人的终点位置连上这个位置相邻的一条直线,并且不能形成 ...

  5. Quadratic equation(二次剩余)2019牛客多校第九场

    链接:https://ac.nowcoder.com/acm/contest/889/B 来源:牛客网 题目描述 Amy asks Mr. B problem B. Please help Mr. B ...

  6. run (牛客多校第二场)计数DP

    链接:https://www.nowcoder.com/acm/contest/140/A 来源:牛客网 题目描述 White Cloud is exercising in the playgroun ...

  7. 【多校训练】2021牛客多校第二场

    [前言] 这是打的第二场,rk39,但是AB这两个比较简单的题都没做emm,大概还是磨合的不够.然后感觉对于阈值类的东西还不是很敏感,应该看到不太好做就直接去想这种阈值的.校内3/9(然后就开启了常年 ...

  8. 2021牛客多校第二场 A——Arithmetic Progression

    题目大意 给你一个长度为 nnn 的数列 aaa ,数列中每个元素都不一样,问你存在多少个区间,这些区间内的数排序后是一个等差数列 解题思路 对于一个区间,如果这个区间内的数排序后的元素可以构成一个等 ...

  9. 2021牛客多校7 - xay loves monotonicity(线段树区间合并)

    题目链接:点击查看 题目大意:给出一个长度为 nnn 的数字序列 aaa 和 010101 序列 bbb,需要执行 mmm 次操作,每次操作分为如下三种类型: 1 x y:修改 a[x]=ya[x]= ...

  10. 2019 牛客多校第一场 F Random Point in Triangle

    题目链接:https://ac.nowcoder.com/acm/contest/881/F 题目大意 给定二维平面上 3 个整数表示的点 A,B,C,在三角形 ABC 内随机选一点 P,求期望$E ...

最新文章

  1. 为了提高工作效率:通过pycharm的模板代码减少重复工作
  2. 2016年6月份学习总结,读书《向着光亮那方》
  3. Android之单复选框及Spinner实现二级联动
  4. 数据结构与算法(一):链表
  5. C语言Catalan number卡特兰数(使用n个键可以搜索多少个二叉搜索树)的算法(附完整源码)
  6. mapreduce,map后面跟map是什么操作???
  7. 运行报错:java.io.IOException: invalid constant type: 15
  8. 嵌入式Linux入门7:kernel移植
  9. Windows Phone 7 有损 缩略图的生成!
  10. Silverlight安装相关问题
  11. libreoffice转换文件为pdf文件乱码问题解决办法
  12. 计算机图形学(一)——数据压缩:道格拉斯普克法
  13. atitit tag标签标示规范 attilax总结 v2 r922.docx
  14. 在页面加载后执行任务
  15. Python4Delphi 安装使用注意
  16. DSP之CCS软件使用一
  17. flash读写学习笔记与spi接口及简单测试验证
  18. python不合法的布尔表达式,python笔试题22-41
  19. 卧槽,这个Vue调试神器牛逼!点击页面元素居然能直接打开对应组件文件…
  20. Navicat重新使自增id从1开始

热门文章

  1. 物流广告收入实现高速增长 国际投行看好京东转型潜力
  2. Processing编程学习指南2.5 Processing中的代码
  3. Server Develop (四) select实现非阻塞sever
  4. [工具开发] 移动梦网短信发送客户端
  5. 公式字符串转换为公式或结果
  6. xcode免证书真机调试iphone(ipad)程序的具体方法(总结贴)转贴)
  7. IDEA+Maven+多个Module模块(创建多模块SpringBoot整合项目)
  8. 如何优雅的统计代码耗时?
  9. 读完《Effective Java》后我淦了 50 条开发技巧
  10. 红芯浏览器终于承认抄袭,研发内核到底有多难:2400万代码