【维护】【线段树】CF413E Maze 2D

【维护】【线段树】CF413E Maze 2D

题目大意

【维护】【线段树】CF413E Maze 2D

给定一个\(2\times n\) 的矩阵,黄色方格代表不能通行,蓝色格子代表畅通无阻,同时对每一个方格进行编号,求编号为x到编号为y的最短路。

思路

先不考虑是具体地从哪里到哪里,而是先进行一个笼统地分析。

单单去考虑从第i行到第j行的最短路。

一共有四种方案:

  1. 左上角到右上角uu
  2. 左上角到右下角ud
  3. 左下角到右上角du
  4. 左下角到右下角dd

而这就是我们需要进行维护的数据

struct data{
    int d1,d2,d3,d4;
}

初始化和合并

【维护】【线段树】CF413E Maze 2D

当考虑长度为1的区间的时候,左上角和右上角是重叠的,左下角和右下角是重叠的。

【维护】【线段树】CF413E Maze 2D

要得到区间为1到9的数据我们只需知道区间1到5的信息和区间6到9的信息。

比如要求得区间1到9从左上角到右上角的最短路。

我们有两种走法

一种是从区间1到5的左上角走到其右上角,再接着从区间6到9的左上角走到区间6到9的右上角。

另外一种是从区间1到5的左上角走到其右下角,再接着从区间6到9的左下角走到区间6到9的右上角。

Code

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define MAX 1000005
#define MOD 1000000007
using namespace std;
const int N = 2E5+500,inf = 8e5+500;
int n,m;
struct Data{
	int uu,ud,du,dd;
};
struct Seg_Tree{
	int l,r;
	Data data;
}tr[N<<2];
bool maze[2][N];

Data merge(Data x,Data y)
{
    Data temp = {inf,inf,inf,inf};
	temp.uu = min(inf, min( x.ud+y.du+1 , x.uu+y.uu+1 ) );
	temp.ud = min(inf, min( x.ud+y.dd+1 , x.uu+y.ud+1 ) );
	temp.du = min(inf, min( x.dd+y.du+1 , x.du+y.uu+1 ) );
	temp.dd = min(inf, min( x.dd+y.dd+1 , x.du+y.ud+1 ) );
	return temp;
}

void build(int u,int l,int r)
{
	if(l==r)
	{
		tr[u].data = {inf,inf,inf,inf};
		if(maze[0][l]) tr[u].data.uu = 0;
		if(maze[1][l]) tr[u].data.dd = 0;
		if(maze[0][l]&&maze[1][l]) tr[u].data.du = tr[u].data.ud = 1; 
	    return ;
	}
	int mid = l + r >> 1 ;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	tr[u].data = merge(tr[u<<1].data,tr[u<<1|1].data);
}

Data query(int u,int l,int r,int x,int y)
{
	if(x<=l&&r<=y)
	   return tr[u].data;
	int mid = l + r >> 1;
	if(mid>=y) return query(u<<1,l,mid,x,y);
	if(mid+1<=x) return query(u<<1|1,mid+1,r,x,y);
	return merge( query(u<<1,l,mid,x,y) , query(u<<1|1,mid+1,r,x,y) );
}

int ask(int x,int y)
{
	int rowx = (x>=n+1) + 1 , rowy = (y>=n+1) + 1;
	int colx = x-(rowx==2?n:0) , coly = y-(rowy==2?n:0);
	if(colx>coly) swap(colx,coly),swap(rowx,rowy);
	Data ans = query(1,1,n,colx,coly);
	int res;
	if(rowx==1&&rowy==1) res = ans.uu;
	else if(rowx==1&&rowy==2) res = ans.ud;
	else if(rowx==2&&rowy==1) res = ans.du;
	else if(rowx==2&&rowy==2) res = ans.dd;
    if(res==inf) return -1;
    return res;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n>>m;
    for(int i=0;i<=1;i++)
    {
    	string s;
    	cin>>s;
    	for(int j=0;j<s.length();j++)
    	   if(s[j]=='.') maze[i][j+1] = 1;
	}
	build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		cin>>x>>y;
		cout<<ask(x,y)<<endl;
	}
    return 0;
}

上一篇:Photoshop为树林逆光人物加上柔和的韩系淡褐色效果


下一篇:(转)列举ASP.NET 页面之间传递值的几种方式