D. Robot Queries
There is an infinite $2$-dimensional grid. Initially, a robot stands in the point $(0, 0)$. The robot can execute four commands:
- U — move from point $(x, y)$ to $(x, y + 1)$;
- D — move from point $(x, y)$ to $(x, y - 1)$;
- L — move from point $(x, y)$ to $(x - 1, y)$;
- R — move from point $(x, y)$ to $(x + 1, y)$.
You are given a sequence of commands $s$ of length $n$. Your task is to answer $q$ independent queries: given four integers $x$, $y$, $l$ and $r$; determine whether the robot visits the point $(x, y)$, while executing a sequence $s$, but the substring from $l$ to $r$ is reversed (i. e. the robot performs commands in order $s_1 s_2 s_3 \dots s_{l-1} s_r s_{r-1} s_{r-2} \dots s_l s_{r+1} s_{r+2} \dots s_n$).
Input
The first line contains two integers $n$ and $q$ ($1 \le n, q \le 2 \cdot 10^5$) — the length of the command sequence and the number of queries, respectively.
The second line contains a string $s$ of length $n$, consisting of characters U, D, L and/or R.
Then $q$ lines follow, the $i$-th of them contains four integers $x_i$, $y_i$, $l_i$ and $r_i$ ($-n \le x_i, y_i \le n$; $1 \le l \le r \le n$) describing the $i$-th query.
Output
For each query, print YES if the robot visits the point $(x, y)$, while executing a sequence $s$, but the substring from $l$ to $r$ is reversed; otherwise print NO.
Examples
input
8 3
RDLLUURU
-1 2 1 7
0 0 3 4
0 1 7 8
output
YES
YES
NO
input
4 2
RLDU
0 0 2 2
-1 -1 2 3
output
YES
NO
input
10 6
DLUDLRULLD
-1 0 1 10
-1 -2 2 5
-4 -2 6 10
-1 0 3 9
0 1 4 7
-3 -1 5 8
output
YES
YES
YES
NO
YES
YES
Note
In the first query of the first sample, the path of the robot looks as follows:
In the second query of the first sample, the path of the robot looks as follows:
In the third query of the first sample, the path of the robot looks as follows:
解题思路
定义 U
关于 $x$ 和 $y$ 的偏移量为 $(0,1)$,同理 R
的偏移量为 $(1,0)$,D
的偏移量为 $(0,-1)$,L
的偏移量为 $(-1,0)$。
定义 $f(i) = (x_i, y_i)$ 表示从坐标 $(0,0)$ 开始执行字符串 $s$ 的前 $i$ 条命令所能到达的坐标(前 $i$ 个 $x$ 的偏移量的和与前 $i$ 个 $y$ 的偏移量的和),容易知道可以通过 $f(i-1)$ 来得到,其中 $f(0) = (0,0)$。对于询问 $(x,y,l,r)$,将 $s$ 的区间 $[l,r]$ 翻转得到 $s'$,再对 $s'$ 求 $f(i)$,是否经过坐标 $(x,y)$ 就等价于是否存在 $i \in [1, n]$ 使得 $f(i) = (x,y)$。可以知道如果直接暴力模拟的话时间复杂度是 $O(n \cdot q)$ 的,容易想到能否只用 $s$ 求得的 $f(i)$ 来处理每一个询问呢。
将 $s'$ 分成以下 $3$ 段区间来考虑:$[0,l-1]$,$[l,r]$,$[r+1,n]$。
对于区间 $[0,l-1]$,没有受到翻转的影响,即 $s'[0,l-1] = s[0,l-1]$,因此只需查看 $i \in [0,l-1]$ 中是否存在 $f(i) = (x,y)$。为了快速判断这里直接开一个 std::map<std::pair<int, int>, std::vector<int>>
记录每个 $f(i) = (x_i, y_i)$ 出现的位置(下标)。如果询问的 $(x,y)$ 有记录且最小下标不超过 $l-1$,那么在这个最小的下标处就有 $f(i) = (x,y)$,否则无解。
对于区间 $[r+1,n]$,同样没有受到翻转的影响,有 $s'[r+1,n] = s[r+1,n]$。这是因为 $x_i$ 本质上是由前 $i$ 个 $x$ 的偏移量求和得到的,因此只要起点不变,无论前 $i$ 条命令以什么顺序执行,求和得到的结果都是一样的。同理 $y_i$。如果询问的 $(x,y)$ 有记录且最大下标至少是 $r+1$,那么在这个最大的下标处就有 $f(i) = (x,y)$,否则无解。
对于区间 $[l,r]$,为了方便这里定义 $g(i) = (x_i, y_i)$ 表示 $s[i, n]$ 中 $x$ 的偏移量的和与 $y$ 的偏移量的和,可以通过 $g(i+1)$ 来得到,同时有 $g(i) = f(n) - f(i-1)$。对于位置 $i \in [l,r]$,可以理解成从起点 $f(l-1)$ 走 $i - (l-1)$ 步到达的坐标,这是对于 $s'$ 而言的。转换到 $s$ 中,这 $i - (l-1)$ 步的偏移量就是 $g(i) - g(r+1)$,那么这个坐标就是 $f(l-1) + g(i) - g(r+1)$。因此若存在解就等价于存在 $i \in [l,r]$ 使得
\begin{align*}
& \quad\;\; f(l-1) + g(i) - g(r+1) = (x,y) \\
&\Rightarrow g(i) = (x,y) - f(l-1) + g(r+1) \\
&\Rightarrow f(n) - f(i-1) = (x,y) - f(l-1) + f(n) - f(r) \\
&\Rightarrow f(i-1) = f(l-1) + f(r) - (x,y)
\end{align*}
为此我们只需在坐标 $f(l-1) + f(r) - (x,y)$ 出现的所有下标中,二分出大于等于 $l-1$ 的最小值,然后判断是否不超过 $r-1$ 即可。
所以我们只需求出关于 $s$ 的 $f(i)$,以及出现 $f(i)$ 的所有下标。
AC 代码如下,时间复杂度为 $O(q \log{n})$:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int N = 2e5 + 10;
char s[N];
PII f[N];
int dx[4] = {0, 1, 0, -1}, dy[4] = {1, 0, -1, 0};
string ss = "URDL";
int main() {
int n, m;
scanf("%d %d %s", &n, &m, s + 1);
map<PII, vector<int>> mp;
mp[make_pair(0, 0)].push_back(0);
for (int i = 1; i <= n; i++) {
f[i] = f[i - 1];
for (int j = 0; j < 4; j++) {
if (s[i] == ss[j]) {
f[i].first += dx[j];
f[i].second += dy[j];
}
}
mp[f[i]].push_back(i);
}
while (m--) {
int x, y, l, r;
scanf("%d %d %d %d", &x, &y, &l, &r);
PII t = make_pair(x, y);
if (mp.count(t) && mp[t][0] <= l - 1) {
printf("YES\n");
}
else if (mp.count(t) && mp[t].back() >= r + 1) {
printf("YES\n");
}
else {
t.first = f[l - 1].first + f[r].first - t.first;
t.second = f[l - 1].second + f[r].second - t.second;
if (!mp.count(t)) {
printf("NO\n");
}
else {
auto it = lower_bound(mp[t].begin(), mp[t].end(), l - 1);
printf("%s\n", it != mp[t].end() && *it < r ? "YES" : "NO");
}
}
}
return 0;
}
参考资料
【A~F 讲解】Educational Codeforces Round 159 (Rated for Div. 2):https://www.bilibili.com/video/BV1Kg4y1f7nX/
标签:le,point,robot,偏移量,Robot,Queries,YES,first From: https://www.cnblogs.com/onlyblues/p/17875949.html