Problem
n
≤
5
,
m
≤
2
×
1
0
5
,
q
≤
5
×
1
0
4
n\leq 5,m\leq 2\times10^5,q\leq 5\times 10^4
n≤5,m≤2×105,q≤5×104
要求支持修改某个格子的可走状态。
Solution
感觉想法很新奇的一道题,但是后来boshi告诉我这是动态dp的套路题……所以就当是动态dp入门题了吧
我们用一个 n 2 n^2 n2的矩阵来代表一个区间的最左端到最右段的各个点间的最短距离,那么合并两个区间就可以枚举中间点, O ( n 3 ) O(n^3) O(n3)。为了方便写代码,可以把这个操作用重载运算符实现。
想到了这一点,一个自然的想法就是用线段树来搞。时间复杂度 O ( n 3 ( m + q ) log m ) O(n^3(m+q)\log m) O(n3(m+q)logm),数据随机所以期望可过。。
Code
#include <cstring>
#include <cstdio>
#define rg register
using namespace std;
typedef long long ll;
const int maxn=200010,INF=0x3f3f3f3f;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int n,m,q,a[6][maxn];
struct data{
int f[6][6];
data(){memset(f,0x3f,sizeof(f));}
void clear(){memset(f,0x3f,sizeof(f));}
data operator + (const data &b)const
{
data res;
for(int i=1;i<=5;i++)
for(rg int j=1;j<=5;j++)
for(rg int k=1;k<=5;k++)
getmin(res.f[i][j],f[i][k]+b.f[k][j]+1);
return res;
}
}t[maxn<<2];
void build(int l,int r,int rt)
{
if(l==r)
{
for(rg int i=1;i<=n;i++)
if(a[i][l])
{
t[rt].f[i][i]=0;
for(rg int j=i+1;j<=n;j++)
if(a[j][l])
{getmin(t[rt].f[i][j],t[rt].f[i][j-1]+1);t[rt].f[j][i]=t[rt].f[i][j];}
}
return ;
}
int m=(l+r)>>1;
build(l,m,rt<<1);build(m+1,r,rt<<1|1);
t[rt]=t[rt<<1]+t[rt<<1|1];
}
void update(int l,int r,int pos,int rt)
{
if(l==r)
{
t[rt].clear();
for(rg int i=1;i<=n;i++)
if(a[i][l])
{
t[rt].f[i][i]=0;
for(rg int j=i+1;j<=n;j++)
if(a[j][l])
{getmin(t[rt].f[i][j],t[rt].f[i][j-1]+1);t[rt].f[j][i]=t[rt].f[i][j];}
}
return ;
}
int m=(l+r)>>1;
if(pos<=m) update(l,m,pos,rt<<1);
else update(m+1,r,pos,rt<<1|1);
t[rt]=t[rt<<1]+t[rt<<1|1];
}
data query(int l,int r,int L,int R,int rt)
{
if(L<=l&&r<=R) return t[rt];
int m=(l+r)>>1;
if(R<=m) return query(l,m,L,R,rt<<1);
if(m<L) return query(m+1,r,L,R,rt<<1|1);
return query(l,m,L,R,rt<<1)+query(m+1,r,L,R,rt<<1|1);
}
int main()
{
int op,x,y,c,d;data tmp;
read(n);read(m);read(q);
for(rg int i=1;i<=n;i++)
for(rg int j=1;j<=m;j++)
read(a[i][j]);
build(1,m,1);
while(q--)
{
read(op);read(x);read(y);
if(op==1)
{
a[x][y]^=1;
update(1,m,y,1);
}
else
{
read(c);read(d);
if(!a[x][y]||!a[c][d]){puts("-1");continue;}
tmp=query(1,m,y,d,1);
printf("%d\n",(tmp.f[x][c]>=INF?-1:tmp.f[x][c]));
}
}
return 0;
}