[2019牛客多校第二场][E. MAZE]
题目链接:https://ac.nowcoder.com/acm/contest/882/E
题目大意:有一个\(n\times m\)的01矩阵,一开始可以从第一行的一个点出发,每次可以向左、向右、向下移动一格且不能回头。中途会有一些点变为障碍物(用1表示),或者从障碍物变回可以通过的格子,同时还需要处理询问:从\((1,a)\)出发,走到\((n,b)\)的方案数有多少种。\(n\leq 50000,\ m\leq 10\)
题解:设\(f(i,j)\)为走到\((i,j)\)的方案数,且第\(i\)行里包含点\((i,j)\)的区间为\([l,r]\),则有\(f(i,j)=\sum_{k=l}^{r}f(i-1,k)\),这里的\(k\)就代表着从前一行的第\(k\)列走下来。可以发现这个转移方程可以转换成一个矩阵形式,即\((f(i,1),f(i,2),...,f(i,m))=(f(i-1,1),f(i-1,2),...,f(i-1,m))\cdot A\)其中\(A\)为状态转移矩阵。求从第\(i-1\)行到第\(i\)行的转移矩阵是可以用\(O(m^2)\)的时间复杂度来实现的。而最后一行的答案就是第一行的状态矩阵乘上这\(n\)行转移矩阵的乘积。在本题中,由于给出了起点和终点,所以若设这\(n\)行转移矩阵的乘积为\(A\),则答案就是\(A(a,b)\)。用线段树维护每行的矩阵以及区间的矩阵乘积即可。
#include<bits/stdc++.h>
using namespace std;
#define N 50001
#define LL long long
#define MOD 1000000007
LL n,m,q,op,x,y,a[N][];
struct Matrix
{
LL n,m;
LL f[][];
void init(LL nn,LL mm)
{
n=nn,m=mm;
for(LL i=;i<=n;i++)
for(LL j=;j<=m;j++)
f[i][j]=;
}
void set_E(LL nn)
{
n=m=nn;
for(LL i=;i<=n;i++)
for(LL j=;j<=n;j++)
f[i][j]=i==j;
}
Matrix operator *(const Matrix &t)const
{
Matrix res;
res.init(n,t.m);
for(LL i=;i<=n;i++)
for(LL j=;j<=t.m;j++)
for(LL k=;k<=m;k++)
(res.f[i][j]+=f[i][k]*t.f[k][j]%MOD)%=MOD;
return res;
}
void get(LL i,LL mm)
{
init(mm,mm);
LL l=,r=;
for(LL j=;j<=m;j++)
{
if(a[i][j]==)
{
l=r=j+;
continue;
}
while(r<=m && a[i][r]==a[i][l])r++;r--;
for(LL k=l;k<=r;k++)
f[k][j]++;
}
}
};
struct Segment_Tree
{
struct rua
{
LL l,r;
Matrix v;
}t[N<<];
void Update(LL x)
{
t[x].v=t[x*].v*t[x*+].v;
}
void Build(LL l,LL r,LL x)
{
t[x].l=l,t[x].r=r;
if(l==r)
{
t[x].v.get(l,m);
return;
}
LL mid=l+r>>;
Build(l,mid,x*);
Build(mid+,r,x*+);
Update(x);
}
void Change(LL x,LL y)
{
LL l=t[x].l,r=t[x].r;
LL mid=l+r>>;
if(l==y && y==r)
{
t[x].v.get(y,m);
return;
}
if(y<=mid)Change(x*,y);
else Change(x*+,y);
Update(x);
}
Matrix Query(LL L,LL R,LL x)
{
LL l=t[x].l,r=t[x].r;
LL mid=l+r>>;
if(L<=l && r<=R)return t[x].v;
Matrix res;
res.set_E(m);
if(L<=mid)res=res*Query(L,R,x*);
if(R>mid)res=res*Query(L,R,x*+);
return res;
}
}T;
LL get()
{
char ch=getchar();
while(ch!='' && ch!='')
ch=getchar();
return ch-'';
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&q);
for(LL i=;i<=n;i++)
for(LL j=;j<=m;j++)
a[i][j]=get();
T.Build(,n,);
while(q--)
{
scanf("%lld%lld%lld",&op,&x,&y);
if(op==)
{
a[x][y]^=;
T.Change(,x);
}
if(op==)
{
Matrix tmp=T.Query(,n,);
printf("%lld\n",tmp.f[x][y]);
}
}
return ;
}
[2019牛客多校第二场][E. MAZE]的更多相关文章
- 2019牛客多校第二场E MAZE(线段树 + 矩阵)题解
题意: n * m的矩阵,为0表示可以走,1不可以走.规定每走一步只能向下.向左.向右走.现给定两种操作: 一.1 x y表示翻转坐标(x,y)的0.1. 二.2 x y表示从(1,x)走到(n,y) ...
- 2019牛客多校第二场 A Eddy Walker(概率推公式)
2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...
- 2019牛客多校第二场H-Second Large Rectangle
Second Large Rectangle 题目传送门 解题思路 先求出每个点上的高,再利用单调栈分别求出每个点左右两边第一个高小于自己的位置,从而而得出最后一个大于等于自己的位置,进而求出自己的位 ...
- [2019牛客多校第二场][G. Polygons]
题目链接:https://ac.nowcoder.com/acm/contest/882/G 题目大意:有\(n\)条直线将平面分成若干个区域,要求处理\(m\)次询问:求第\(q\)大的区域面积.保 ...
- 2019 牛客多校第二场 H Second Large Rectangle
题目链接:https://ac.nowcoder.com/acm/contest/882/H 题目大意 给定一个 n * m 的 01 矩阵,求其中第二大的子矩阵,子矩阵元素必须全部为 1.输出其大小 ...
- 2019牛客多校第二场H题(悬线法)
把以前的题补补,用悬线求面积第二大的子矩形.我们先求出最大子矩阵的面积,并记录其行三个方向上的悬线长度.然后排除这个矩形,记得还得特判少一行或者少一列的情况 #include <bits/std ...
- 2019牛客多校第二场D-Kth Minimum Clique
Kth Minimum Clique 题目传送门 解题思路 我们可以从没有点开始,把点一个一个放进去,先把放入一个点的情况都存进按照权值排序的优先队列,每次在新出队的集合里增加一个新的点,为了避免重复 ...
- 2019牛客多校第二场F-Partition problem(搜索+剪枝)
Partition problem 题目传送门 解题思路 假设当前两队的对抗值为s,如果把红队中的一个人a分配到白队,s+= a对红队中所有人的对抗值,s-= a对白队中所有人的对抗值.所以我们可以先 ...
- 2019牛客多校第二场BEddy Walker 2——BM递推
题意 从数字 $0$ 除法,每次向前走 $i$ 步,$i$ 是 $1 \sim K$ 中等概率随机的一个数,也就是说概率都是 $\frac{1}{K}$.求落在过数字 $N$ 额概率,$N=-1$ 表 ...
随机推荐
- 在UPW中使用VLC解码媒体
VLC支持的格式很全,学会如何使用后,完全可以自己给自己写一个简单的万能播放器了. 源码来自github:https://github.com/kakone/VLC.MediaElement.git( ...
- uva11624 Fire! (bfs预处理)
题目链接:https://vjudge.net/problem/UVA-11624 题意:给一个1000×1000的矩阵,有几个着火点和Joe,着火点和Joe每个单位时间均移动一个单位,求Joe逃出的 ...
- [LuoguP3064][USACO12DEC]伊斯坦布尔的帮派Gangs of Istanbull(加强版)_线段树_贪心
伊斯坦布尔的帮派Gangs of Istanbull 题目链接:https://www.luogu.org/problem/P3064 数据范围:略. 题解: 这个题其实分为两问,第一问是$YES$. ...
- Mac启动Mysql,停止Mysql,重启Mysql
1.启动mysql sudo /usr/local/mysql/support-files/mysql.server start 2.停止mysql sudo /usr/local/mysql/sup ...
- LRU算法简介
LRU是什么? 按照英文的直接原义就是Least Recently Used,最近最久未使用法,它是按照一个非常注明的计算机操作系统基础理论得来的:最近使用的页面数据会在未来一段时期内仍然被使用,已经 ...
- 第七章 ZYNQ-MIZ701 GPIO使用之EMIO
7.0难度系数★☆☆☆☆☆☆ 7.1硬件截图 7.1.1 PCB上的位置 7.1.1 PCB上的位置 7.2电路分析 本次实验用到的是LD_A0~LD_A3,管脚定义如下表所示. LD_A0:F17 ...
- 【leetcode】153. 寻找旋转排序数组中的最小值
题目链接:传送门 题目描述 现有一个有序数组,假设从某个数开始将它后面的数按顺序放到了数组前面.(即 [0,1,2,4,5,6,7] 可能变成 [4,5,6,7,0,1,2]). 请找出数组中的最小元 ...
- React-脚手架
1. Node和NPM 版本 2. 脚手架 在对React比较熟悉之前,为了避免陷入到开发工具的繁琐配置中,借助react官方提供的脚手架工具Create React App来搭建React应用 np ...
- java中数组的定义
1. 一维数组 int[] arr = new int[3];//需要一个容器,但是暂时不给具体的数值 int[] arr = new int[3]{1,2,3};//直接给定具体数值 int[] a ...
- js面向对象的几种方式
对象的字面量 var obj={}:创建实例对象 var obj=new Object();构造函数模式 function fn(){}, new fn();工厂模式:用一个函数,通过传递参数返回对象 ...