CF1902D题解

题解 · 2023-12-10

题意

有一个无限的 $2$ 维网格。一开始,机器人站在 $(0, 0)$ 点。机器人可以执行四条指令:

  • U:从点 $(x, y)$ 移动到 $(x, y + 1)$ ;
  • D:从点 $(x, y)$ 移动到 $(x, y - 1)$ ;
  • L:从点 $(x, y)$ 移动到 $(x - 1, y)$ ;
  • R:从点 $(x, y)$ 移动到 $(x + 1, y)$ 。

给你一串长度为 $n$ 的命令 $s$ 。您的任务是回答 $q$ 独立的查询:给定四个整数 $x$ 、 $y$ 、 $l$ 和 $r$ ;判断机器人在执行命令序列 $s$ 时是否访问了点 $(x, y)$ ,但 $l$ 到 $r$ 的子串是相反的(即机器人执行命令的顺序是 $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$ )。

题解

每次查询,机器人的路径分为三个部分:

  1. $[1, l - 1]$;
  2. $[l, r - 1]$;
  3. $[r, n]$。

我们可以开个map,记录下每个点分别在第几步之后到达,于是第一三部分就很容易做掉了。

对于第二部分,我们设 $a_i $ 为原操作序列走完 $i$ 步后的位置,设翻转后中第 $k$ 步走完后到达 $(x, y)$($l \le k < r$),则有 $a_r - a_k$ 为走完 $l - 1$ 步后产生的偏移量(第 $r$ 步走到第 $k$ 步和第 $k$ 步走到 $r$ 步产生的总偏移量是相同的),所以 $a_l + a_r - a_k = (x, y)$。移项得到 $a_l + a_r - (x, y) = a_k$,于是我们可以在map里找到点 $a_l + a_r - (x, y)$,然后看有无 $k$ 使得第 $k$ 步走完后到达点 $a_l + a_r - (x, y)$ 且满足 $l \le k < r$。

#include <iostream>
#include <map>
#include <algorithm>
#include <vector>
using namespace std;
int n, q;
pair <int, int> a[200010];
string s;
map <pair <int, int>, vector <int>> p;
bool find (pair <int, int> x, int l, int r) {
  if (p.find (x) == p.end ()) return false;
  auto id = lower_bound (p.begin (), p.end (), l);
  return (id != p.end () && *id <= r);
} //查询 a[l~r]中有无点x 
int main () {
  ios::sync_with_stdio (false);
  cin.tie (0);
  cin >> n >> q;
  cin >> s; s = ' ' + s;
  p[{0, 0}].push_back (0);
  a[0] = {0, 0};
  for (int x = 0, y = 0, i = 1; i <= n; i++) {
    x += (s[i] == 'R') - (s[i] == 'L');
    y += (s[i] == 'U') - (s[i] == 'D');
    a[i] = {x, y};
    p[{x, y}].push_back (i);
  }
  while (q--) {
    int x, y, l, r;
    cin >> x >> y >> l >> r;
    bool flag = false;
    flag |= find ({x, y}, 0, l - 1);
    flag |= find ({x, y}, r, n);
    flag |= find ({a[r].first + a[l - 1].first - x, a[r].second + a[l - 1].second - y}, l, r - 1);
    cout << (flag ? "YES" : "NO") << '\n';
  }
  return 0;
}
题解
Theme Jasmine by Kent Liao