D. Robot Queries

发布时间 2023-12-04 20:57:52作者: onlyblues

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/