题目链接:
题目
有一个外星人控制了你的大脑。一开始你处于原点。外星人有一个由组成的长度为的操作序列,分别代表(右,上,下,左)。
平面上有个关键点,每当外星人给出一个操作,你需要在这个方向上找到最近的一个关键点,并走到那个点上。保证输入数据合法。
上图为第三个样例的图示。
输入
第一行两个整数 , 。
接下来行,每行两个整数 , ,代表第个点的座标。
接下来一行,一个长度为的字符串,代表操作序列。
输出
一行两个整数,代表最终你所处的位置。
样例输入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
数据范围
的数据,,。
的数据, , 。
思路
这道题我们模拟, 但是要用二分优化。
我们将座标的每一行和每一列所包含的座标点从小到大排序,然后要移动的时候,就用二分来找下一个座标是在哪里。
(由于座标有负数,我就直接先把所有点的,座标都加上,然后输出答案的时候再减回去)
还有一点要注意的,就是人在向左移动和向下移动的时候,我们二分要先找到原来的点的位置,再往前挪一个。这样得到的新的点就是我们要的那个点了。
代码
#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;
}