CodeForces 413E

2*N的矩形,有些位置可以走,有些位置不能走,
问两点之间最短路

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=2e5+100;

char ss[2][N];
int chs(int i,int j){
    if(ss[i][j]=='X')return 1;
    return 0;
}

int chw(int i,int j){
    if(chs(i^1,j)||chs(i^1,j-1))return 1;
    return 0;
}


int wall[N];
int n,m;
void getw(){
    wall[0]=0;
    for(int i=1;i<=n;i++){
        wall[i]=wall[i-1];
        if(chs(0,i)&&chw(0,i)||chs(1,i)&&chw(1,i)){
            wall[i]++;
        }
    }
}
int zhu[2][N];
void getzhu(){
    int x0=0,x1=0;
    zhu[0][x0]=zhu[1][x0]=0;
    for(int i=1;i<=n;i++){
        if(x0>x1){
            zhu[0][i]=zhu[0][x0];
            zhu[1][i]=zhu[0][x0];
            if(chs(1,i)){
                zhu[1][i]++;
            }
        }
        else {
            zhu[0][i]=zhu[1][x1];
            zhu[1][i]=zhu[1][x1];
            if(chs(0,i)){
                zhu[0][i]++;
            }
        }
        if(chs(0,i))x0=i;
        if(chs(1,i))x1=i;
    }
}

vector<int > v1,v2;
#define pb push_back
#define pii(a,b) (a*n+b-1)

void getv(){
    v1.clear();
    v2.clear();
    for(int i=1;i<=n;i++)if(chs(0,i)){
        v1.pb(pii(0,i));
    }
    for(int i=1;i<=n;i++)if(chs(1,i)){
        v1.pb(pii(1,i));
    }
    for(int i=n;i>=1;i--)if(chs(1,i)){
        v2.pb(pii(1,i));
    }
    for(int i=n;i>=1;i--)if(chs(0,i)){
        v2.pb(pii(0,i));
    }
}
int getl(int a,int a1,int b,int b1){
    return abs(b-a)+abs(a1-b1);
}
void pri(int aa[N]){
    //for(int i=0;i<=n;i++)printf("%d ",aa[i]);printf("\n");
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi

    while(scanf("%d%d",&n,&m)!=EOF){
        ss[0][0]=ss[1][0]='X';
        scanf("%s%s",ss[0]+1,ss[1]+1);
//        printf("%s\n%s\n",ss[0],ss[1]);
        getw();
        pri(wall);
        getzhu();
        pri(zhu[0]);pri(zhu[1]);
        getv();
//        for(int i=0;i<v1.size();i++)printf("%d ",v1[i]);printf("\n");
//        for(int i=0;i<v2.size();i++)printf("%d ",v2[i]);printf("\n");
        for(int i=0;i<m;i++){
            int a,a1,b,b1;scanf("%d%d",&a,&b);a--;b--;
            a1=a%n+1,a=a/n;
            b1=b%n+1,b=b/n;
            if(a1>b1||a1==b1&&a<b){
                swap(a1,b1);swap(a,b);
            }
            if(chs(a,a1)||chs(b,b1)){
                printf("-1\n");continue;
            }
            if(wall[b1]-wall[a1]){
                printf("-1\n");continue;
            }
            int x=lower_bound(v1.begin(),v1.end(),pii(a,a1))-v1.begin();
            int y=lower_bound(v2.begin(),v2.end(),pii(b,b1),greater<int>())-v2.begin();
            if(x==v1.size()||y==v2.size()){
                printf("%d\n",getl(a,a1,b,b1));continue;
            }
            int x1,y1;
            x1=v1[x]%n+1,x=v1[x]/n;
            y1=v2[y]%n+1,y=v2[y]/n;
//            printf("%d %d %d %d\n",a,a1,b,b1);
//            printf("%d %d %d %d\n",x,x1,y,y1);
            if(x!=a||y!=b){
                printf("%d\n",getl(a,a1,b,b1));continue;
            }
            if(y1<x1){
                printf("%d\n",getl(a,a1,b,b1));continue;
            }
            int num=zhu[y][y1]-zhu[x][x1]+1;
//            printf("%dasdf\n",num);
            printf("%d\n",b1-a1+num+1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值