题意

有一个 n×mn \times mn×m 的网格上放满了 1×21 \times 21×2 的多米诺骨牌,你可以拿走某个多米诺骨牌,然后让剩下某个多米诺骨牌沿着它的长边移动一格(必须要有空位相邻才能移动),这样会让两个空格的位置产生变化。问最终可以产生多少种不同的两个空格位置。

题解

写了个做法死活过不了样例 3,看到有人写 SegBeats 还以为自己假了,检查了半天,结果是扫描线写挂了……

首先冷静分析一下,把空格看成是独立的点,每次移动多米诺骨牌就相当于把空格沿着多米诺骨牌的长边移动两格。

于是按照上述移动方式连有向边,比如一个 (a,b),(a,b+1)(a,b),(a,b+1)(a,b),(a,b+1) 的多米诺骨牌,就连边 (a,b−1)→(a,b+1)(a,b-1) \rightarrow (a,b+1)(a,b−1)→(a,b+1) 和 (a,b+2)→(a,b)(a,b+2) \rightarrow (a,b)(a,b+2)→(a,b),然后来分析一下这个图的性质。

  1. 该图无环。如果产生环,那么这个环包住的内部空间含有奇数个方格(可以画一画验证一下),与题意不符(不能被多米诺骨牌完全覆盖)。
  2. 该图是一个有向树森林。连边方式决定了一个点有且仅有一条入边。
  3. 对于网格图上相邻的两个格子,他们对应的点在图中不在一个连通块。将原图黑白染色,显然一个连通块中所有格子颜色相同。

但是移动之后会不会出现某个多米诺骨牌连续向右移动两格的情况?如果这样的话那么上面的图是没法处理的。但是这种情况不可能发生,不然初始状态下直接删除那个移动两次的多米诺骨牌即可。

于是问题转化为:一个有根树森林,每次把 uuu 的子树和 vvv 的子树中的点两两配对扔到一个 set 里,问最后 set 的 size。求出该森林的 dfs 序,就变成了每次加入一个矩形,求所有矩形的面积并。扫描线即可,复杂度 O(nlog⁡n)O(n \log n)O(nlogn)。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
template<typename T> inline void chkmin(T &a, const T &b) { a = a < b ? a : b; }
template<typename T> inline void chkmax(T &a, const T &b) { a = a > b ? a : b; }const int MAXN = 200005, MAXT = 1 << 19;
char *mp[MAXN], mem[MAXN];
int beg[MAXN], ed[MAXN], sum[MAXT], tag[MAXT], n, m, tot;
vector<int> edge[MAXN];
struct Opt { int l, r, tp; };
vector<Opt> md[MAXN];void dfs(int u) {assert(!beg[u]);beg[u] = ++tot;for (int v : edge[u]) dfs(v);ed[u] = tot;
}void modify(int a, int b, int t, int l = 1, int r = tot, int k = 1) {if (a > r || b < l) return;if (a <= l && b >= r) {tag[k] += t;sum[k] = tag[k] ? r - l + 1 : (l == r ? 0 : sum[k << 1] + sum[k << 1 | 1]);return;}int mid = (l + r) >> 1;modify(a, b, t, l, mid, k << 1);modify(a, b, t, mid + 1, r, k << 1 | 1);sum[k] = tag[k] ? r - l + 1 : sum[k << 1] + sum[k << 1 | 1];
}int main() {scanf("%d%d", &n, &m);for (int i = 0; i < n; i++) {mp[i] = mem + i * m;scanf("%s", mp[i]);}for (int i = 0; i < n; i++)for (int j = 0; j < m; j++) {char c = mp[i][j]; int p = i * m + j;if (c == 'U' && i + 2 < n)edge[(i + 2) * m + j].push_back(p);else if (c == 'D' && i > 1)edge[(i - 2) * m + j].push_back(p);else if (c == 'L' && j + 2 < m)edge[p + 2].push_back(p);else if (c == 'R' && j > 1)edge[p - 2].push_back(p);else edge[n * m].push_back(p);}dfs(n * m);assert(tot == n * m + 1);for (int i = 0; i < n; i++)for (int j = 0; j < m; j++) if (~(i + j) & 1) {char c = mp[i][j];int p = i * m + j, q;if (c == 'U') q = p + m;else if (c == 'D') q = p - m;else if (c == 'L') q = p + 1;else q = p - 1;md[beg[p]].push_back(Opt { beg[q], ed[q], 1 });md[ed[p] + 1].push_back(Opt { beg[q], ed[q], -1 });}LL ans = 0;for (int i = 1; i <= tot; i++) {for (const Opt &o : md[i])modify(o.l, o.r, o.tp);ans += sum[1];}printf("%lld\n", ans);return 0;
}
···

CF 1368G Shifting Dominoes相关推荐

  1. CF1368G Shifting Dominoes(扫描线求矩阵的并集)

    CF1368G Shifting Dominoes problem solution code problem 题目链接 solution 求的是最后棋盘本质不同的个数,而本质不同等价于两个空格位置不 ...

  2. [VOT14](2022CVPR)CSWinTT: Transformer Tracking with Cyclic Shifting Window Attention

    先贴一个算法整体框架图: Abstract 问题背景:Transformer架构得益于其有效的注意力机制已经在目标跟踪领域展示了巨大的优势. 提出问题:现有的Transformer追踪器都采用了在拉展 ...

  3. 『参考』.net CF组件编程(4)——为自定义组件添加工具箱图标!

    前言: 在前三篇的文章中,和大家一起创建了一个用于TCP连接检测的小组件,如果你记不得了,可以通过以下链接去回顾一下: 『参考』.net CF组件编程(1)--基础之后 『参考』.net CF组件编程 ...

  4. OC对象 vs CF对象

    2019独角兽企业重金招聘Python工程师标准>>> OC对象 vs CF对象 在ARC场景下,对象所有权没有转换 使用__bridge关键字即可实现CF对象和OC对象之间的自由转 ...

  5. CF 990A. Commentary Boxes【数学/模拟】

    [链接]:CF [题意]:对于一个数n,每次加一的代价是a,每次减一的代价是b,求被m整除时的最小代价. [分析]:分情况讨论,自己多举几个栗子. [代码]: #include<cstdio&g ...

  6. hdu 2518 Dominoes

    Dancing Links--- 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2518 Dominoes Time Limit: 2000/1000 ...

  7. 推荐算法——基于协同过滤CF

    https://www.toutiao.com/a6643326861214482957/ 2019-01-06 18:21:09 前边我们已经介绍了推荐算法里的基于内容的推荐算法CB,今天我们来介绍 ...

  8. 索引贴——移动开发(.Net CF 停止更新)

    这是关于本人博客的技术索引贴,希望能方便的让您阅读到相关技术文章--不断更新中.一整理才发现,好多啊,哈哈- 一..Net CF技巧:搜集.转载一些和CF开发相关的辅助文章,比较适合初学者.开发入门者 ...

  9. 解答:CF截图保存在哪

    为什么80%的码农都做不了架构师?>>>    大家玩CF(穿越火线)的时候遇到精彩的画面总希望截图保存下来,然而有些游戏玩家截图后却不知道CF截图保存在哪!这不得不说是个悲剧,但是 ...

最新文章

  1. RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个
  2. suse软件管理程序zypper
  3. Eclipse中新建SpringBoot项目完成对json、pojo、map、list的请求
  4. ASP.NET MVC5+EF6+EasyUI 后台管理系统(19)-权限管理系统-用户登录
  5. wxWidgets:wxToggleButton类用法
  6. 2021安徽省计算机应用基础,安徽省高等教育自学考试2021年4月课程考试时间安排表.pdf...
  7. 最新“母马”病毒反杀主流杀毒软件
  8. ZH奶酪:Ubuntu 14.04配置LAMP(Linux、Apache、MySQL、PHP)
  9. 程序员面试金典——番外篇之下一个较大元素I
  10. pl/sql developer安装与配置
  11. Linux 中的旧扣簧键盘(Bucklespring 键盘)声音
  12. 【2019上海网络赛:D】Counting Sequences I(dfs+多重集合排列)
  13. 【2018宁夏邀请赛 L】Continuous Intervals【线段树】
  14. C语言 全局变量和局部变量的区别
  15. Unity3d 周分享(8期 2018.12.16)
  16. 对计算机硬盘进行格式化操作,如何禁止对电脑硬盘进行格式化操作?电脑中怎么防止格式化硬盘...
  17. LIBCURL.LIB
  18. “Windows10 无法打开这个应用程序”解决方案
  19. 网络编程之端口:端口号为什么常见是8000、8080、8888...
  20. 默的各种写法图片_默字的意思、默的繁体字、默的笔顺笔画、默字部首和繁体字默的意思...

热门文章

  1. 玩转移远SC60 Android开发板------(1)LCD
  2. 自动驾驶域控制器话题下的软件系统设计和研发管理
  3. 推荐书籍:软件定义网络 SDN与OpenFlow解析
  4. 点击“安全删除硬件并弹出媒体”不显示可删除移动设备
  5. 爬取免费代理,拥有自己的代理池
  6. MOSS 2007 入门(3) : 建立一个最精简的母版页
  7. Zabbix5.0如何发送短信
  8. java高性能rpc,企业级rpc,zk调度,负载均衡,泛化调用一体的rpc服务框架
  9. 恒生期货交易时间(恒生指数期货交割日期)
  10. 51单片机实战之电子时钟