• CodeForces413E Maze 2D


    题意

    给一个(2*n)的迷宫,有障碍物,(m)次询问,每次查询两点间最短路

    题解

    把上下当成一个点,每个点有上下两个接口
    用线段树维护
    根据地图初始化每个点信息
    然后合并区间信息(类似(floyd))
    想明白了写出来还是很简单
    然后查询两点距离即可

    为什么这样不会错?
    画图可以知道
    因为宽为(2)
    所以最短路肯定不会先在区间外绕一圈再回来
    所以查询也是直接查询两点在区间内的最小距离就是答案
    如果宽更大就必须保证不能向左走才可以这么做(不然为什么还需要最短路算法,线段树还支持修改)
    比如宽为(3)时就可能区间内不联通
    但是可以绕一圈到达

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define gc c=getchar()
    #define r(x) read(x)
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    
    template<typename T>
    inline void read(T&x){
        x=0;T k=1;char gc;
        while(!isdigit(c)){if(c=='-')k=-1;gc;}
        while(isdigit(c)){x=x*10+c-'0';gc;}x*=k;
    }
    
    const int INF=1e9;
    
    const int N=2e5;
    
    char s[2][N];
    
    struct seg{
    	int dist[2][2];
    	
    	const int* operator [](const int &x)const{
    		return dist[x];
    	}
    	
    	int* operator [](const int &x){
    		return dist[x];
    	}
    	
    }tr[N<<2];
    
    inline seg operator +(const seg &a,const seg &b){
    	seg ret;
    	for(int i=0;i<2;++i){
    		for(int j=0;j<2;++j){
    			ret[i][j]=INF;
    			for(int k=0;k<2;++k)ret[i][j]=min(ret[i][j],a[i][k]+b[k][j]+1);
    		}
    	}
    	return ret;
    }
    
    inline void build(int rt,int l,int r){
    	if(l==r){
    		tr[rt][0][0]=tr[rt][0][1]=tr[rt][1][1]=tr[rt][1][0]=INF;
    		if(s[0][l]=='.'){
    			tr[rt][0][0]=0;
    			if(s[1][l]=='.')tr[rt][0][1]=1;
    		}
    		if(s[1][l]=='.'){
    			tr[rt][1][1]=0;
    			if(s[0][l]=='.')tr[rt][1][0]=1;
    		}
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(ls,l,mid);
    	build(rs,mid+1,r);
    	tr[rt]=tr[ls]+tr[rs];
    }
    
    inline seg query(int rt,int l,int r,int x,int y){
    	if(x<=l&&r<=y)return tr[rt];
    	int mid=(l+r)>>1;
    	if(y<=mid)return query(ls,l,mid,x,y);
    	else if(x>mid)return query(rs,mid+1,r,x,y);
    	else return query(ls,l,mid,x,y)+query(rs,mid+1,r,x,y);
    }
    
    int n,m;
    
    inline int Query(int x,int y){
    	int l=(x-1)%n+1;
    	int r=(y-1)%n+1;
    	if(l>r)swap(l,r),swap(x,y);
    	return query(1,1,n,l,r)[x>n][y>n];
    }
    
    int main(){
    	r(n),r(m);
    	scanf("%s",s[0]+1);
    	scanf("%s",s[1]+1);
    	build(1,1,n);
    	for(int a,b;m;--m){
    		r(a),r(b);
    		int ans=Query(a,b);
    		if(ans==INF)ans=-1;
    		printf("%d
    ",ans);
    	}
    }
    
    
  • 相关阅读:
    Spring事务原理分析-部分二
    Spring事务原理分析-部分一
    Spring 通读官方文档
    Spring IOC 源码解析
    SpringAOP原理分析
    Docker学习笔记
    TCP、UDP和HTTP关系
    洛谷P3312
    洛谷P3327
    BZOJ3073
  • 原文地址:https://www.cnblogs.com/yicongli/p/9745547.html
Copyright © 2020-2023  润新知