外星人的路径

外星人的路径

题目链接:jzoj 5234jzoj\ 5234

题目

有一个外星人控制了你的大脑。一开始你处于原点0,0(0,0)。外星人有一个由(R,U,D,L)(R,U,D,L)组成的长度为MM的操作序列,分别代表(右,上,下,左)。
平面上有NN个关键点,每当外星人给出一个操作,你需要在这个方向上找到最近的一个关键点,并走到那个点上。保证输入数据合法。
在这里插入图片描述
上图为第三个样例的图示。

输入

第一行两个整数NN , MM
接下来NN行,每行两个整数xix_i , yiy_i,代表第ii个点的座标。
接下来一行,一个长度为MM的字符串,代表操作序列。

输出

一行两个整数,代表最终你所处的位置。

样例输入1

4 4
1 1
1 0
0 1 
0 0
RULD

样例输出1

0 0

样例输入2

7 5
0 0
0 1
0 -1
1 0
1 -1
3 0
3 -1
DRRUD

样例输出2

3 -1

样例输入3

10 6
0 0
1 1
2 1
0 2
-1 2
-1 3
2 3
2 4
4 3
2 -1
ULURDL

样例输出

1 1

数据范围

56%56\%的数据,N3000N≤3000M3000M≤3000
100%100\%的数据,N,M100000N,M≤100000 , xi,yi200000x_i,y_i≤200000

思路

这道题我们模拟, 但是要用二分优化。

我们将座标的每一行和每一列所包含的座标点从小到大排序,然后要移动的时候,就用二分来找下一个座标是在哪里。
(由于座标有负数,我就直接先把所有点的xxyy座标都加上200001200001,然后输出答案的时候再减回去)

还有一点要注意的,就是人在向左移动和向下移动的时候,我们二分要先找到原来的点的位置,再往前挪一个。这样得到的新的点就是我们要的那个点了。

代码

#include<vector>
#include<cstdio>
#include<algorithm>
#define addnum 200001

using namespace std;

int n, m, x, y, nx = addnum, ny = addnum;
vector<int>a[addnum << 1];
vector<int>b[addnum << 1]; 

int main() {
//	freopen("tratincice.in", "r", stdin);
//	freopen("tratincice.out", "w", stdout);
	
	scanf("%d %d", &n, &m);//读入
	for (int i = 1; i <= n; i++) {
		scanf("%d %d", &x, &y);//读入
		x += addnum;//使所有的座标都是正数
		y += addnum;
		a[x].push_back(y);
		b[y].push_back(x);
	}
	
	for (int i = 1; i < addnum << 1; i++) {
		if (!a[i].empty())
			sort(a[i].begin(), a[i].end());//将行排序
		if (!b[i].empty())
			sort(b[i].begin(), b[i].end());//将列排序
	}
	
	for (int i = 1; i <= m; i++) {
		char c = getchar();
		while (c != 'R' && c != 'L' && c != 'D' && c != 'U') c = getchar();
		if (c == 'R') {//向右
			int l = 0, r = b[ny].size() - 1;
			while (l < r) {
				int mid = (l + r) >> 1;
				if (b[ny][mid] <= nx) l = mid + 1;
					else r = mid;
			}
			nx = b[ny][l];
		}
		else if (c == 'L') {//向左
			int l = 0, r = b[ny].size() - 1;
			while (l < r) {
				int mid = (l + r) >> 1;
				if (b[ny][mid] < nx) l = mid + 1;
					else r = mid;
			}
			while (b[ny][l] == nx) l--;
			nx = b[ny][l];
		}
		else if (c == 'D') {//向下
			int l = 0, r = a[nx].size() - 1;
			while (l < r) {
				int mid = (l + r) >> 1;
				if (a[nx][mid] < ny) l = mid + 1;
					else r = mid;
			}
			while (a[nx][l] == ny) l--;
			ny = a[nx][l];
		}
		else {//向上
			int l = 0, r = a[nx].size() - 1;
			while (l < r) {
				int mid = (l + r) >> 1;
				if (a[nx][mid] <= ny) l = mid + 1;
					else r = mid; 
			}
			ny = a[nx][l];
		}
	}
	
	printf("%d %d", nx - addnum, ny - addnum);//输出(记得减200001)
	
//	fclose(stdin);
//	fclose(stdout);
	
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章