题解 CF413E 【Maze 2D】
竟然没人写题解?我来水一篇~~
其实感觉应该是提高+/省选-的样子,233。
其实我没咕值子
先说说思路:
- 维护一个[l,r]区间中四个角相互之间的最短路
- 查询时用二分
思路出来了,算法也就出来了,那就是——线段树!
此处应有掌声
首先,我们知道线段树是二分维护区间值的。
然后,我们也知道线段树是二分查找值。
最后,我们发现这道题没有修改。
紧接着,我们开始写代码。
#include<bits/stdc++.h>
using namespace std;
int mmp[3][200001];
#define INF 500000000
int n;
int ans;
char c[300001];
struct data{
int d1,d2,d3,d4; //四个最短路
};
struct tree{
int l, r;
data d;
}t[4*200001]; //线段树标准结构体
data merge(data a,data b) //合并最短路
{
data s;
s.d1=min(INF,min(a.d1+b.d1,a.d2+b.d3)+1);
s.d2=min(INF,min(a.d1+b.d2,a.d2+b.d4)+1);
s.d3=min(INF,min(a.d3+b.d1,a.d4+b.d3)+1);
s.d4=min(INF,min(a.d3+b.d2,a.d4+b.d4)+1);
return s;
}
void init(int s,int l,int r) //标准线段树构建
{
t[s].l=l,t[s].r=r;
if(l==r){
t[s].d.d1=t[s].d.d2=t[s].d.d3=t[s].d.d4=INF;
if(mmp[1][l]) t[s].d.d1=0;
if(mmp[2][l]) t[s].d.d4=0;
if(mmp[1][l]&&mmp[2][l]) t[s].d.d2=t[s].d.d3=1;
return ;
}
int m=(l+r)/2;
init(2*s,l,m);
init(2*s+1,m+1,r);
t[s].d=merge(t[2*s].d,t[2*s+1].d);
}
data q(int s,int x,int y) //查询时的合并
{
int l=t[s].l,r=t[s].r;
if(x==l&&y==r) return t[s].d;
int m=(l+r)/2;
/*下面分类讨论不用讲了吧*/
if(m>=y) return q(2*s,x,y); //毒瘤呀,少写return
else if(m<x) return q(2*s+1,x,y); //毒瘤呀,少写return
else
return merge(q(2*s,x,m),q(2*s+1,m+1,y));
}
void ask(int x,int y) //查询最短路
{
int a=(x-1)%n+1,b=(y-1)%n+1;
if(a>b){
swap(x,y);
swap(a,b);
}
data s=q(1,a,b); //找到最短路
/*根据情况返回四种路径的最短路*/
if(x<=n&&y<=n) ans=s.d1;
if(x<=n&&y>n) ans=s.d2;
if(x>n&&y<=n) ans=s.d3;
if(x>n&&y>n) ans=s.d4;
}
int main() //请从这里开始阅读,这是一个好习惯
{
int m;
cin>>n>>m;
int i,j;
for(i=1;i<=2;i++) //无脑O(2n)读入
{
scanf("%s",c);
for(j=1;j<=n;j++)
if(c[j-1]=='.') mmp[i][j]=1;
}
init(1,1,n);
int x,y;
for(i=1;i<=m;i++){ //无脑查询
cin>>x>>y;
ask(x,y);
if(ans<INF) cout<<ans<<endl;
else cout<<"-1\n";
}
return (0-0); //无脑卖萌QAQ
}
千万记得所有查询都要return
!
为没有出修改题的出题人喝彩!!!
有志者,事竟成,破釜沉舟,百二秦关终属楚; 苦心人,天不负,卧薪尝胆,三千越甲可吞吴!