codeforces1073C. Vasya and Robot(二分+字首和)
C. Vasya and Robot
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Vasya has got a robot which is situated on an infinite Cartesian plane, initially in the cell (0,0)(0,0). Robot can perform the following four kinds of operations:
- U — move from (x,y)(x,y) to (x,y+1)(x,y+1);
- D — move from (x,y)(x,y) to (x,y−1)(x,y−1);
- L — move from (x,y)(x,y) to (x−1,y)(x−1,y);
- R — move from (x,y)(x,y) to (x+1,y)(x+1,y).
Vasya also has got a sequence of nn operations. Vasya wants to modify this sequence so after performing it the robot will end up in (x,y)(x,y).
Vasya wants to change the sequence so the length of changed subsegment is minimum possible. This length can be calculated as follows: maxID−minID+1maxID−minID+1, where maxIDmaxID is the maximum index of a changed operation, and minIDminID is the minimum index of a changed operation. For example, if Vasya changes RRRRRRR to RLRRLRL, then the operations with indices 22, 55 and 77 are changed, so the length of changed subsegment is 7−2+1=67−2+1=6. Another example: if Vasya changes DDDD to DDRD, then the length of changed subsegment is 11.
If there are no changes, then the length of changed subsegment is 00. Changing an operation means replacing it with some operation (possibly the same); Vasya can't insert new operations into the sequence or remove them.
Help Vasya! Tell him the minimum length of subsegment that he needs to change so that the robot will go from (0,0)(0,0) to (x,y)(x,y), or tell him that it's impossible.
Input
The first line contains one integer number n (1≤n≤2⋅105)n (1≤n≤2⋅105) — the number of operations.
The second line contains the sequence of operations — a string of nn characters. Each character is either U, D, L or R.
The third line contains two integers x,y (−109≤x,y≤109)x,y (−109≤x,y≤109) — the coordinates of the cell where the robot should end its path.
Output
Print one integer — the minimum possible length of subsegment that can be changed so the resulting sequence of operations moves the robot from (0,0)(0,0) to (x,y)(x,y). If this change is impossible, print −1−1.
Examples
input
Copy
5 RURUU -2 3
output
Copy
3
input
Copy
4 RULR 1 1
output
Copy
0
input
Copy
3 UUU 100 100
output
Copy
-1
Note
In the first example the sequence can be changed to LULUU. So the length of the changed subsegment is 3−1+1=33−1+1=3.
In the second example the given sequence already leads the robot to (x,y)(x,y), so the length of the changed subsegment is 00.
In the third example the robot can't end his path in the cell (x,y)(x,y).
一、原題地址
二、大致題意
給出一個機器人行走的路徑,還有一個終點的座標。現在可以修改機器人行走路徑上的一段,詢問最短修改長度為多少的路徑,可以使機器人到達給定的終點座標。不行則輸出-1.
三、思路
機器人行走的每一步先後順序其實是沒有意義的,這也是這道題的關鍵。
正因為這一點,我們可以將每一步在座標上的偏移量單獨提取出來,然後用字首和累加,這樣的話就可以快速的得到在一段[ l , r ]區間上機器人實際偏移的座標。
先找出機器人在無修改的情況下對於( 0,0 )的偏移記作sx , sy ,那麼修改操作實際上就是先把一段區間內的偏移量刪去,然後再加上我們想要加上的偏移量。
記去掉替換區間後的位置在nowx,nowy ,可以計算出該點到達終點的曼哈頓距離 dis 。想要保證我們列舉的區間符合條件就需要保證我們替換上去的區間長度 len 奇偶性和終點的曼哈頓距離 dis 一致,並且保證len>=dis。
至於機器人到底是怎麼走的我們不需要考慮,因為一定是會有一種走法符合的。
以上操作是可以n^2實現的,當然是超時的,所以二分一下替換的區間長度就是nlogn的做法了。程式碼跑了31ms.
四、程式碼
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<set>
#include<map>
#include<unordered_set>
#include<vector>
using namespace std;
const int inf = 0x3f3f3f3f;
typedef long long LL;
int n;
char s[200005];
int ex, ey;
int x[200005], y[200005];
void prework()
{
scanf("%d", &n);
scanf("%s", s + 1);
scanf("%d %d", &ex, &ey);
for (int i = 1; i <= n; i++)
{
if (s[i] == 'R')
{
x[i] = 1; y[i] = 0;
}
else if (s[i] == 'L')
{
x[i] = -1; y[i] = 0;
}
else if (s[i] == 'U')
{
x[i] = 0; y[i] = 1;
}
else if (s[i] == 'D')
{
x[i] = 0; y[i] = -1;
}
}
for (int i = 1; i <= n; i++)
{
x[i] = x[i - 1] + x[i];
y[i] = y[i - 1] + y[i];
}
return;
}
bool check(int len)
{
int sx = x[n], sy = y[n];
for (int i = 1; i + len - 1 <= n; i++)
{
int tl = i, tr = i + len - 1;
int movex = x[tr] - x[tl - 1];
int movey = y[tr] - y[tl - 1]; //替換部分被去掉的偏移量
int nowx = sx - movex, nowy = sy - movey; //去掉替換部分後的所在位置
int dis = abs(nowx - ex) + abs(nowy - ey);
if (dis <= len && ((dis & 1) && (len & 1) || ((dis % 2 == 0) && (len % 2 == 0))))return true;
}
return false;
}
void Mainwork()
{
int l = 0, r = n;
int mid, ans;
bool tag = false;
while (l <= r)
{
mid = (l + r) >> 1;
if (check(mid))
{
ans = mid;
r = mid - 1;
tag = true;
}
else l = mid + 1;
}
if(tag) printf("%d\n", ans);
else printf("-1\n");
return;
}
int main()
{
prework();
Mainwork();
getchar();
getchar();
return 0;
}