移动

news/2024/9/29 19:22:30

移动

题意

有一个 \(n\times m\) 的网格图,有 \(k\) 个点不能走。

每次移动可以向右或向下走,只能走两次。

求能走到的点的个数。

思路

可以发现只能是从第一排向下走或从第一列向右走。

统计上下走能到的点和左右走能到的点,减去重复的即可。

扫描 \(x\),使用线段树维护 \(y\) 每一个位置能否被上下走到。

初始第一行时,从 \(1\) 到第一个不能走的点的左边都赋成 \(1\),其他设为 \(0\)

扫描每一行时,若有一个点不能走,把它设为 \(0\),其它不变,继承上一行。

这样就维护好了上下走的情况,答案先加上线段树里 \(1\) 的个数(其实就是区间求和)。

容易发现左右走只会走到最左边的不能走的格子的左边。

答案加上这些格子的数量,减去这些格子中在线段树里已经为 \(1\) 的个数(重复的)。

注意扫描到第一列最靠上的不能走的位置时,它和下面的行就不能左右走了。因为 \((1,1)\) 没法走到它们。

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;template <typename T>
void read(T& x) {x = 0; T f = 1;char ch = getchar();while (ch < '0' || ch > '9') {if (ch == '-') f = -f;ch = getchar();}while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}x = x * f;
}const int N = 2e5 + 5;struct segt {struct node {int l, r;int cnt, tag;} t[N << 2];#define ls (p << 1)#define rs (p << 1 | 1)void build(int p, int l, int r) {t[p].tag = -1, t[p].l = l, t[p].r = r;if (l == r) return ;int mid = (l + r) >> 1;build(ls, l, mid);build(rs, mid + 1, r);}void make(int p, int v) {t[p].tag = v;t[p].cnt = v * (t[p].r - t[p].l + 1);}void push_down(int p) {if (t[p].tag != -1) {make(ls, t[p].tag);make(rs, t[p].tag);t[p].tag = -1; }}void modify(int p, int l, int r, int v) {if (l <= t[p].l && t[p].r <= r) {make(p, v);return ;}push_down(p);if (l <= t[ls].r) modify(ls, l, r, v);if (r >= t[rs].l) modify(rs, l, r, v);t[p].cnt = t[ls].cnt + t[rs].cnt; }int query(int p, int l, int r) {if (l <= t[p].l && t[p].r <= r) {return t[p].cnt;}push_down(p);int res = 0;if (l <= t[ls].r) res += query(ls, l, r);if (r >= t[rs].l) res += query(rs, l, r);return res;}
} T;int n, m, k, Min[N];
struct point {int x, y;
} a[N];
vector <int> v[N];
ll ans;int main() {read(n); read(m); read(k);for (int i = 1; i <= n; i ++) Min[i] = m + 1;int minx = 1e9;for (int i = 1; i <= k; i ++) {read(a[i].x); read(a[i].y);Min[a[i].x] = min(Min[a[i].x], a[i].y);v[a[i].x].push_back(a[i].y);if (a[i].y == 1) minx = min(minx, a[i].x);}T.build(1, 1, m);T.modify(1, 1, Min[1] - 1, 1);ans += Min[1] - 1; for (int i = 2; i <= n; i ++) {for (auto y : v[i]) T.modify(1, y, y, 0);ans += T.query(1, 1, m);if (Min[i] != 1 && i < minx) // i < minx 注意ans += Min[i] - 1 - T.query(1, 1, Min[i] - 1);}cout << ans << "\n";return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/66279.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

prometheus学习笔记之alertmanager告警配置

一、安装alertmanager 项目地址:https://github.com/prometheus/alertmanager 帮助文档:https://prometheus.io/docs/alerting/latest/alertmanager/ 配置文档:https://prometheus.io/docs/alerting/latest/configuration/wget https://github.com/prometheus/alertmanager/…

[clickhouse] Clickhouse 关键特性的版本支持与演变

clickhouse 21.10 Feature : UDF用户可通过添加lambda表达式,创建自定义FunctionCREATE FUNCTION linear_equation AS (x, k, b) -> k*x + b; SELECT number, linear_equation(number, 2, 1) FROM numbers(3);CREATE FUNCTION parity_str AS (n) -> if(n % 2, odd, even…

RTE 大会报名丨智能编解码和 AI 生成视频 ,RTE2024 技术专场第五弹!

AI 视频的爆炸增长,给新一代编解码技术提出了什么新挑战?语音 AI 实现 human-like 的最后一步是什么?当大模型进化到实时多模态,又将诞生什么样的新场景和玩法?所有 AI Infra 都在探寻规格和性能的最佳平衡,如何构建高可用的云边端协同架构?AI 加持下,空间计算和新硬件…

在docker安装Python环境提供给其他docker使用

1. 在宿主机新建一个目录 2. 在app目录下新建一个Dockerfile文件 本文永久更新地址:1. 在宿主机新建一个目录 在宿主机上新建一个目录如app/,在app目录里面导入项目需要依赖的包 在项目根目录下输入命令,导出python项目所有的依赖包 pip freeze > requirements.txt把导出的…

南沙C++信奥赛陈老师解一本通题 1942:【08NOIP普及组】ISBN号码

​【题目描述】每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版…

9.29每日总结

今天做完了“四则运算”和“生成验证码”,其中“生成验证码”这道题暑假的时候跟着网课做过初级版的,今天又加以改进了不少,为此把黑马的字符串章节差不多看完了,收获比较大的除了StringBuilder和StringJoiner之外,就是“验证码”这道题中用到的字符串转为字符数组(toCha…