外星人的路徑

外星人的路徑

題目鏈接: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;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章