当前位置: 首页 > news >正文

ABC429F Shortest Path Query 题解

AtCoder

写在前面

赛时没想出来,赛后经过大神和题解点拨有点思路了。之前确实没咋遇见过多少线段树维护矩阵的题。那就写写题解当积累trick了吧。

题意

给出一张\(3 \times N\) 的矩阵,内含# . 两种字符。其中# 代表该位置不能被经过,. 代表该位置能被经过。我们还有若干次操作,每次操作给出一个坐标,然后将这个坐标上的字符类型取反。我们可以向上下左右移动。求问在每次操作后从\((1,1)\)\((3,N)\) 需要走的最小步数是多少。若无法到达\((3,N)\) 则输出-1

思路

赛时没有任何可行的思路,想过BFS等等乱七八糟的东西,但是由于有修改操作所以难以实现。但是其实正解的根本已经想到了,只不过不知道有这样的trick qwq。

我们注意到每次只会修改一个位置,而一个位置能影响的范围是有限的。比如修改一个位置状态无法使\((1,1)\) 到其左边点的步数改变。虽然能改变其右边点到\((3,N)\) 的步数,但是实际上从某个位置开始其无法再改变步数。所以修改一个位置的状态只会影响一个有限的区间,而幸运的是各个区间具有独立性和可合并性,然后我们就将本题转化为了一个区间修改和区间合并的问题。然后考虑用某种数据结构支持这种操作。那这就摆明了是线段树啊。

考虑线段树维护的信息。令\(t_{i,j,u}\)\(u\) 节点所代表的区间从最左边的第\(i\) 行到最右边的第\(j\) 行的最小步数。然后显然pushup的时候可以枚举中转点,即左儿子的右端点和右儿子的左端点,然后取所有端点中作为中转点答案最小的那个的答案即可。然后就能做到\(O(logn)\) 修改了。

然后初始化时就将. 代表的点点权赋为1,# 代表的点点权赋为INF。然后将线段树叶子节点赋为对应的点权或点权和即可。

对于查询,我们直接取\(t_{1,3,1}\) 的值即可。

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10,inf=INT_MAX;
typedef long long ll;
int n,q;
ll a[4][maxn];
#define lc(u) (u<<1)
#define rc(u) (u<<1|1)
ll t[4][4][maxn<<2];
inline void pushup(int u){for(int i=1;i<=3;i++)for(int j=1;j<=3;j++){t[i][j][u]=inf;for(int k=1;k<=3;k++) t[i][j][u]=min(t[i][j][u],t[i][k][lc(u)]+t[k][j][rc(u)]);}
}
inline void build(int u,int l,int r){if(l==r){t[1][1][u]=a[1][l];t[2][2][u]=a[2][l];t[3][3][u]=a[3][l];t[1][3][u]=t[3][1][u]=a[3][l]+a[2][l]+a[1][l];t[1][2][u]=t[2][1][u]=a[2][l]+a[1][l];t[2][3][u]=t[3][2][u]=a[3][l]+a[2][l];return;}int mid=(l+r)>>1;build(lc(u),l,mid);build(rc(u),mid+1,r);pushup(u);
}
inline void update(int u,int l,int r,int p,int pos,int k){if(l==r){a[pos][l]=k;t[1][1][u]=a[1][l];t[2][2][u]=a[2][l];t[3][3][u]=a[3][l];t[1][3][u]=t[3][1][u]=a[3][l]+a[2][l]+a[1][l];t[1][2][u]=t[2][1][u]=a[2][l]+a[1][l];t[2][3][u]=t[3][2][u]=a[3][l]+a[2][l];return;}int mid=(l+r)>>1;if(p<=mid) update(lc(u),l,mid,p,pos,k);else update(rc(u),mid+1,r,p,pos,k);pushup(u);
}
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>n;char c;for(int i=1;i<=3;i++)for(int j=1;j<=n;j++)cin>>c,a[i][j]=(c=='.'?1:inf);a[1][1]=0;build(1,1,n);cin>>q;for(int i=1,x,y;i<=q;i++){cin>>x>>y;if(a[x][y]!=inf) update(1,1,n,y,x,inf);else update(1,1,n,y,x,1);cout<<(t[1][3][1]>=inf?-1:t[1][3][1])<<'\n';}return 0;
}
http://www.rkmt.cn/news/30630.html

相关文章:

  • 苏维埃日报08.高三生福音?大屏课表软件ClassIsland助你度过高三
  • 创建平面设计网站-全-
  • 2025年靠谱的方形冷却塔,横流式冷却塔用户口碑最好的厂家榜
  • 2025年知名的薄型液压缸,多级液压缸实力厂家TOP推荐榜
  • 2025年优质的定量包装机,自动吨袋包装机厂家最新用户好评榜
  • 2025年优质的移动盘式过滤机,真空过滤机最新TOP品牌厂家排行
  • 2025年优质的涤纶单层网布,鞋材单层网布厂家最新推荐权威榜
  • 2025年靠谱的粉末冶金,粉末冶金齿轮厂家推荐及采购参考
  • 2025年热门的吸塑PET片,食品级PET片品牌厂家排行榜
  • 2025年热门的发电机组,柴油发电机组厂家最新推荐排行榜
  • quicker目录
  • [SHELL] 个人BASH配置与美化
  • [AI应用开发平台] Coze:AI应用开发平台
  • [网络] [TOOL] 为什么要使用ss工具替代netstat?
  • [网络] [TCP] Linux UDP Socket 学习指南
  • 品牌故事不会写?这个AI指令可能帮你解决大问题
  • 电梯调度编程结对项目总结
  • 第二次作业--田佳吉
  • 启动分布式mapreduce的过程以及prompt
  • 20232310 2025-2026-1 《网络与系统攻防技术》实验三实验报告
  • [SWPUCTF 2024 秋季新生赛]http标头 WP
  • 20251025 之所思 - 人生如梦
  • 为什么Java/Python程序无需关心内存释放?揭秘垃圾回收(GC)的核心概念
  • 从图像到文本:详解藏文OCR的实现过程与核心技术
  • Jerrum–Sinclair 全有或全无定理
  • 初步学习计算机相关知识有感 - fang
  • RuoYi-Cloud 认证实现
  • 每日反思(2025_10_25)
  • AtCoder Beginner Contest 429 ABCDEF 题目解析
  • How to Build an Agent