D. Robot Queries
D. Robot Queries
There is an infinite -dimensional grid. Initially, a robot stands in the point . The robot can execute four commands:
- U — move from point to ;
- D — move from point to ;
- L — move from point to ;
- R — move from point to .
You are given a sequence of commands of length . Your task is to answer independent queries: given four integers , , and ; determine whether the robot visits the point , while executing a sequence , but the substring from to is reversed (i. e. the robot performs commands in order ).
Input
The first line contains two integers and () — the length of the command sequence and the number of queries, respectively.
The second line contains a string of length , consisting of characters U, D, L and/or R.
Then lines follow, the -th of them contains four integers , , and (; ) describing the -th query.
Output
For each query, print YES if the robot visits the point , while executing a sequence , but the substring from to 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
关于 和 的偏移量为 ,同理 R
的偏移量为 ,D
的偏移量为 ,L
的偏移量为 。
定义 表示从坐标 开始执行字符串 的前 条命令所能到达的坐标(前 个 的偏移量的和与前 个 的偏移量的和),容易知道可以通过 来得到,其中 。对于询问 ,将 的区间 翻转得到 ,再对 求 ,是否经过坐标 就等价于是否存在 使得 。可以知道如果直接暴力模拟的话时间复杂度是 的,容易想到能否只用 求得的 来处理每一个询问呢。
将 分成以下 段区间来考虑:,,。
对于区间 ,没有受到翻转的影响,即 ,因此只需查看 中是否存在 。为了快速判断这里直接开一个 std::map<std::pair<int, int>, std::vector<int>>
记录每个 出现的位置(下标)。如果询问的 有记录且最小下标不超过 ,那么在这个最小的下标处就有 ,否则无解。
对于区间 ,同样没有受到翻转的影响,有 。这是因为 本质上是由前 个 的偏移量求和得到的,因此只要起点不变,无论前 条命令以什么顺序执行,求和得到的结果都是一样的。同理 。如果询问的 有记录且最大下标至少是 ,那么在这个最大的下标处就有 ,否则无解。
对于区间 ,为了方便这里定义 表示 中 的偏移量的和与 的偏移量的和,可以通过 来得到,同时有 。对于位置 ,可以理解成从起点 走 步到达的坐标,这是对于 而言的。转换到 中,这 步的偏移量就是 ,那么这个坐标就是 。因此若存在解就等价于存在 使得
为此我们只需在坐标 出现的所有下标中,二分出大于等于 的最小值,然后判断是否不超过 即可。
所以我们只需求出关于 的 ,以及出现 的所有下标。
AC 代码如下,时间复杂度为 :
#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/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17875949.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-12-04 火车进栈