ARC190C 题解
写篇题解,来给 THUWC 攒功德了。
这篇题解给出的做法不需要考虑
考虑修改一个点的权值之后整个网格图权值的变化量是什么。
显然,点权修改只会对经过这个点的路径的权值产生影响。
如果我们记
注意特判
且经过点
这个式子的意义是,由于一条路径可以从上方 / 左方进入点
如果我们以
对此,我们可以采取如下方法:新建布尔数组
进一步,我们会发现题目中给的限制会带来一个非常好的性质:每次修改的位置是相邻的,这意味着每次修改之后
具体地,由于每次修改的位置相邻,于是操作后
至于究竟是 UDLR 有关,读者可以自己尝试画一画、推导结论,因为一一讲述实在很麻烦。
那么到现在,我们只剩下两个问题了。
在处理新的询问时,如果我们需要知道某个点的
f 、g 值,而此处的f 、g 值恰好由于之前a 数组被修改而修改了,应该如何处理?
使用记忆化搜索解决。以
看上去这么暴力的算法,其时间复杂度真的可以接受吗?
在上文的基础上,再加一点点剪枝就可以了。
首先注意到很重要的一点:记忆化搜索的总时间复杂度不会大于修改
所以不妨计算一下我们对
考虑剪枝,在修改
于是我们以一个比较水到渠成的思路解决了这道难度评分
只可惜因为
代码主要在赛时完成,仅供参考。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define pii pair<int,int>
const int N=2e5+10,mod=998244353;
int n,m,Q,x,y,ans;
int dx[200],dy[200];
vector<int> a[N],f[N],g[N];
vector<bool> bf[N],bg[N];
void upf(int i,int j){
if(i==1&&j==1) f[i][j]=a[i][j];
else f[i][j]=(f[i-1][j]+f[i][j-1])*a[i][j]%mod;
}
void upg(int i,int j){
if(i==n&&j==m) g[i][j]=a[i][j];
else g[i][j]=(g[i+1][j]+g[i][j+1])*a[i][j]%mod;
}
int fet(int i,int j){
if(i==1&&j==1) return bf[i][j]=0,a[i][j];
if(!bf[i][j]) return f[i][j];
bf[i][j]=0;
return f[i][j]=(fet(i-1,j)+fet(i,j-1))*a[i][j]%mod;
}
int get(int i,int j){
if(i==n&&j==m) return bg[i][j]=0,a[i][j];
if(!bg[i][j]) return g[i][j];
bg[i][j]=0;
return g[i][j]=(get(i+1,j)+get(i,j+1))*a[i][j]%mod;
}
signed main(){
ios::sync_with_stdio(false);
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
cin>>n>>m;
dx['U']=-1;
dx['D']=1;
dy['L']=-1;
dy['R']=1;
for(int i=0;i<=n+1;++i) a[i].resize(m+10),bf[i].resize(m+10),bg[i].resize(m+10),f[i].resize(m+10),g[i].resize(m+10);
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
cin>>a[i][j];
upf(i,j);
}
}
for(int i=n;i;--i){
for(int j=m;j;--j){
upg(i,j);
}
}
ans=g[1][1];
int x,y,v,op;
char ch;
cin>>Q>>x>>y;
for(int i=1;i<=x;++i){
for(int j=1;j<=y;++j){
bg[i][j]=1;
}
}
for(int i=x;i<=n;++i){
for(int j=y;j<=m;++j){
bf[i][j]=1;
}
}
while(Q--){
cin>>ch>>v;
op=(int)ch;
bf[x][y]=bg[x][y]=1;
x+=dx[op],y+=dy[op];
int sf=fet(x-1,y)+fet(x,y-1),sg=get(x+1,y)+get(x,y+1);
if(x==1&&y==1) sf=1;
if(x==n&&y==m) sg=1;
ans=(ans+sf*sg%mod*(v-a[x][y])%mod+mod)%mod;
a[x][y]=v;
fet(x,y),get(x,y);
cout<<ans<<'\n';
if(dx[op]<0||dy[op]<0){
for(int i=x,j=y;i<=n&&j<=m;i-=dy[op],j-=dx[op]){
if(bf[i][j]) break;
bf[i][j]=1;
}
}
if(dx[op]>0||dy[op]>0){
for(int i=x,j=y;i&&j;i-=dy[op],j-=dx[op]){
if(bg[i][j]) break;
bg[i][j]=1;
}
}
}
return 0;
}