题解 CF413E 【Maze 2D】

竟然没人写题解?我来水一篇~~

其实感觉应该是提高+/省选-的样子,233。

其实我没咕值子

先说说思路:

  1. 维护一个[l,r]区间中四个角相互之间的最短路
  2. 查询时用二分

思路出来了,算法也就出来了,那就是——线段树!

此处应有掌声

首先,我们知道线段树是二分维护区间值的。

然后,我们也知道线段树是二分查找值。

最后,我们发现这道题没有修改。

紧接着,我们开始写代码。

#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!

为没有出修改题的出题人喝彩!!!

转载于:https://www.cnblogs.com/Garbage-Only-one/p/11141878.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值