1. 程式人生 > >Vasya and Robot- 二分搜尋- Educational Codeforces Round 53 (Rated for Div. 2)

Vasya and Robot- 二分搜尋- Educational Codeforces Round 53 (Rated for Div. 2)

題目傳送門
題意:
機器人初始位置在(0,0),然後輸入一串指令有R,L,D,U,分別向x,y方向行走,R:x+1,L:x-1,U:y+1,D:y-1;。然後輸入目標位置,要你求需要改變的最短區間的長度,使得機器人可以走到目標位置,如果不能則輸出-1.
思路:
求最小區間長度,我們可以二分搜尋區間長度。
先預處理,求出所有區間的字首和,二分最短區間的長度。關鍵設計好check()函式,列舉所有長度為mid的區間,然後通過字首和計算出所學要改變區間需要對x,y做出的貢獻(因為改變的區間的貢獻是不定的,所以通過sum-不需要改變區間的貢獻)。

AC code:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
typedef long long LL;
int sx[maxn],sy[maxn];
char s[maxn];
int n = 0,x = 0,y = 0;
bool check(int m){
	for(int i = 1;i + m -1 <= n;++i){//列舉所有長度為m的區間 
		int xx = sx[n] - (sx[i+m-1] - sx[i-1]);//不需要改變區間對x,y的貢獻值 
		int yy = sy[n] - (sy[i+m-1] - sy[i-1]);
		
		int tx = x - xx,ty = y - yy;//要改變區間對x,y的貢獻值 
		if(abs(tx) + abs(ty) <= m && (m - (abs(tx) + abs(ty))) % 2 == 0){
			return true;
		}
	}
	return false;
}
int main(){
	while(~scanf("%d",&n)){
		fill(sx,sx+maxn,0);fill(sx,sx+maxn,0);
		scanf("%s",s+1);
		scanf("%d %d",&x,&y);
		
		for(int i = 1;i <= n;++i){//計算字首和 
			sx[i] = sx[i-1] + (s[i] == 'R' ? 1 : (s[i] == 'L' ? -1 : 0));
			sy[i] = sy[i-1] + (s[i] == 'U' ? 1 : (s[i] == 'D' ? -1 : 0));
		}
		
		int ans = -1,l = 0,r = n;
		while(l <= r){//二分搜尋區間長度 
			int mid = (l + r ) >> 1;
			if(check(mid)){
				ans = mid;
				r = mid -1;
			}else{
				l = mid + 1;
			}
		}
		printf("%d\n",ans);
	}
	
	return 0;
}