二分+前缀和+思维,CF 1902D - Robot Queries

目录

一、题目

1、题目描述

2、输入输出

2.1输入

2.2输出

3、原题链接

二、解题报告

1、思路分析

2、复杂度

3、代码详解


一、题目

1、题目描述

2、输入输出

2.1输入

2.2输出

3、原题链接

1902D - Robot Queries


二、解题报告

1、思路分析

不管怎么反转:

起点终点不变

[0, l - 1] 的路径上的点不变

[r, n] 的路径上的点不变

记 op[l - 1]后,坐标为(lx, ly),op[r] 后 为(rx, ry),询问(x, y),[l, r] 的 x偏移量为dx,[l, r]的y偏移量为dy

反转前,我们从(lx, ly) 走 (dx, dy) 走到 (rx, ry)

反转后,相当于从(lx, ly) 走 (dx1, dy1) 到(x, y),再从(x, y) 走 (dx2, dy2) 到 (rx, ry)

其中 dx1 + dx2 = dx, dy1 + dy2 = dy

显然dx1 = rx - x, dy1 = ry - y

即到达(x, y)时候的操作下标为k,那么(dx1, dy1)就是[l, k] 操作的偏移量

我们只需判断 (x, y) 是否在[0, l - 1] || [r, n]出现,以及[lx + dx1, ly + dy1] 是否在[l, r - 1]出现

2、复杂度

时间复杂度: O(NlogN + q logq)空间复杂度:O(N)

3、代码详解

 ​
#include <bits/stdc++.h>

using i64 = long long;
using i32 = unsigned int;
using u64 = unsigned long long;
using i128 = __int128;

constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
constexpr int P = 998'244'353;

void solve() {
	int n, q;
	std::cin >> n >> q;

	std::string s;
	std::cin >> s;

	std::map<std::pair<int, int>, std::vector<int>> mp;

	std::vector<std::pair<int, int>> pos(n + 1);

	mp[std::pair(0, 0)].push_back(0);

	for (int i = 0; i < n; ++ i) {
		pos[i + 1].first = pos[i].first + (s[i] == 'R') - (s[i] == 'L');
		pos[i + 1].second = pos[i].second + (s[i] == 'U') - (s[i] == 'D');
		mp[pos[i + 1]].push_back(i + 1);
	}


	auto check = [&](const std::pair<int, int> &p, int l, int r) -> bool {
		if (!mp.contains(p)) return false;
		auto it = std::lower_bound(mp[p].begin(), mp[p].end(), l);
		return it != mp[p].end() && *it <= r;
	};

	for (int i = 0, x, y, l, r; i < q; ++ i) {
		std::cin >> x >> y >> l >> r;

		int nx = pos[l - 1].first + pos[r].first - x, ny = pos[l - 1].second + pos[r].second - y;

		bool f = check(std::pair(x, y), 0, l - 1) ||
			check(std::pair(nx, ny), l, r - 1) ||
			check(std::pair(x, y), r, n);

		f ? std::cout << "YES\n" : std::cout << "NO\n";
	}
}

auto FIO = []{
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout.tie(nullptr);
	return 0;
}();

int main () {
	#ifdef DEBUG
		freopen("in.txt", "r", stdin);
		freopen("out.txt", "w", stdout);
	#endif
	
	int T = 1;
	// std::cin >> T;
	while (T --)
		solve();

	return 0;
}

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值