\(\text{Solution}\)

这个问题是不好判断的

考虑简单点的,\((1,1)\) 到 \((h,w)\) 是否连通

那么只要在最外围一圈 #(显然一些位置不能加),判断 \((h+1,n)\) 和 \((0,w+1)\) 是否能通过 # 八连通即可

如果是双连通呢?只要这两点所在连通块不能通过只加一个 # 就连通

看起来很不可做的题猜测一些简单结论就很可做了

判断否就考虑加一个 # 就连通的位置,这个 # 必然是连接了两个连通块

考虑这两个连通块的类别,一是新填的两个 #,O(k^2) 枚举即可

二是连接了原图中的两个连通块,这两个连通块又通过新的 # 连通了 \((h+1,n)\) 或 \((0,w+1)\)

于是把所有这样的连通块记录下来,判断两两是否在原图中只加一个 # 就连通

三是一个新 # 和原图中的连通块,发现处理可以和二一样

判断两连通块是否只加一个 # 就连通可以用哈希表预处理

一次询问是临时的,可撤销并查集即可

\(\text{Code}\)

#include <bits/stdc++.h>
#define IN inline
#define eb emplace_back
using namespace std; int n, m, q, id[1005][1005];
char str[1005], mp[1005][1005]; const int N = 1e6 + 5e3;
struct DSU {
int fa[N], sz[N], top;
struct Edge{int u, v;}stk[N];
IN int find(int x){while (fa[x] != x) x = fa[x]; return x;}
IN void merge(int x, int y) {
int u = find(x), v = find(y);
if (u == v) return; if (sz[u] > sz[v]) swap(u, v);
fa[u] = v, sz[v] += sz[u], stk[++top] = Edge{u, v};
}
IN void clear(int lst) {
for(int u, v; top != lst; --top)
u = stk[top].u, v = stk[top].v, sz[v] -= sz[u], fa[u] = u;
}
}T1, T2; int fx[9][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}, {1, 1}, {-1, -1}, {1, -1}, {-1, 1}};
unordered_map<int, int> hs[N]; void dfs(int x, int y, int d, int p) {
if ((x == 2 && y == 2) || (x == n - 1 && y == m - 1)) return;
if (mp[x][y] == '#') hs[p][T1.find(id[x][y])] = 1;
if (!d) return;
for(int k = 0; k < 8; k++) {
int xx = x + fx[k][0], yy = y + fx[k][1];
if (id[xx][yy]) dfs(xx, yy, d - 1, p);
}
} void Init() {
scanf("%d%d%d", &n, &m, &q), n += 2, m += 2;
for(int i = 2; i < n; i++) scanf("%s", mp[i] + 2);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) id[i][j] = (i - 1) * m + j;
for(int j = 1; j <= m; j++) mp[1][j] = mp[n][j] = '#';
for(int i = 1; i <= n; i++) mp[i][1] = mp[i][m] = '#';
mp[1][1] = mp[1][2] = mp[2][1] = mp[n - 1][m] = mp[n][m - 1] = mp[n][m] = '.';
for(int i = 1; i <= n * m; i++) T1.fa[i] = i, T1.sz[i] = 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) if (mp[i][j] == '#')
for(int k = 0; k < 8; k++) {
int x = i + fx[k][0], y = j + fx[k][1];
if (id[x][y] && mp[x][y] == '#') T1.merge(id[i][j], id[x][y]);
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++) dfs(i, j, 2, T1.find(id[i][j]));
for(int i = 1; i <= n * m; i++) T2.fa[i] = T1.fa[i], T2.sz[i] = T1.sz[i];
} int X[15], Y[15]; int main() {
Init();
for(; q; --q) {
int K; scanf("%d", &K);
for(int i = 1; i <= K; i++) scanf("%d%d", &X[i], &Y[i]), mp[++X[i]][++Y[i]] = '#';
int lst = T2.top;
for(int i = 1; i <= K; i++)
for(int k = 0; k < 8; k++) {
int x = X[i] + fx[k][0], y = Y[i] + fx[k][1];
if (id[x][y] && mp[x][y] == '#') T2.merge(id[X[i]][Y[i]], id[x][y]);
}
int flag = 0;
for(int i = 1; i <= K && !flag; i++)
for(int j = 1; j <= K; j++) if (max(abs(X[i] - X[j]), abs(Y[i] - Y[j])) <= 2) {
if (T2.find(id[X[i]][Y[i]]) == T2.find(id[1][m]) && T2.find(id[X[j]][Y[j]]) == T2.find(id[n][1])) {
flag = 1; break;
}
}
vector<int> Vr, Vl; Vr.eb(T1.find(id[1][m])), Vl.eb(T1.find(id[n][1]));
for(int i = 1; i <= K; i++) {
for(int k = 0; k <= 8; k++) {
int x = X[i] + fx[k][0], y = Y[i] + fx[k][1];
if (id[x][y] && T2.find(id[x][y]) == T2.find(id[1][m])) Vr.eb(T1.find(id[x][y]));
if (id[x][y] && T2.find(id[x][y]) == T2.find(id[n][1])) Vl.eb(T1.find(id[x][y]));
}
}
for(auto kr : Vr) for(auto kl : Vl)
if (hs[kr].find(kl) != hs[kr].end() || hs[kl].find(kr) != hs[kl].end()){flag = 1; break;}
if (!flag) puts("YES"); else puts("NO"); fflush(stdout);
T2.clear(lst); for(int i = 1; i <= K; i++) mp[X[i]][Y[i]] = '.';
}
}

CF750H New Year and Snowy Grid的更多相关文章

  1. ZJOI2018游记Round1

    广告 ZJOI2018Round2游记 All Falls Down 非常感谢学弟学妹们捧场游记虽然这是一篇假游记 ZJOI Round1今天正式落下帷幕.在这过去的三天里遇到了很多朋友,见识了很多有 ...

  2. ExtJS 4.2 Grid组件的单元格合并

    ExtJS 4.2 Grid组件本身并没有提供单元格合并功能,需要自己实现这个功能. 目录 1. 原理 2. 多列合并 3. 代码与在线演示 1. 原理 1.1 HTML代码分析 首先创建一个Grid ...

  3. WPF中Grid实现网格,表格样式通用类

    /// <summary> /// 给Grid添加边框线 /// </summary> /// <param name="grid"></ ...

  4. 在 Windows Phone 中,为 Grid 添加 Tilt 效果

    在 Windows Phone 中,Tilt 效果是比较经典的效果,我们可以很简单的为按钮等控件添加这样的效果(使用 Windows Phone Toolkit 的Tilt 效果),但是,如果我们想要 ...

  5. wpf 列表、菜单 收起与展开,通过Grid DoubleAnimation或者Expander实现

    菜单收缩有很多种方法具体如何实现还是看个人想法: 第一种通过后台控制收起与展开: 效果图: 代码 : <Grid> <Grid.ColumnDefinitions> <C ...

  6. Sencha ExtJS 6 Widget Grid 入门

    最近由于业务需要,研究了一下Sencha ExtJS 6 ,虽然UI和性能上据相关资料说都有提升,但是用起来确实不太顺手,而且用Sencha cmd工具进行测试和发布,很多内部细节都是隐藏的,出了问题 ...

  7. WPF CheckBox样式 ScrollViewer样式 WrapPanel、StackPanel、Grid布局

    本节讲述布局,顺带加点样式给大家看看~单纯学布局,肯定是枯燥的~哈哈 那如上界面,该如何设计呢? 1.一些布局元素经常用到.Grid StackPanel Canvas WrapPanel等.如上这种 ...

  8. [转]ExtJS Grid 分页时保持选中的简单实现方法

    原文地址 :http://www.qeefee.com/article/ext-grid-keep-paging-selection ExtJS中经常要用到分页和选择,但是当选择遇到分页的时候,杯具就 ...

  9. [转]extjs grid的Ext.grid.CheckboxSelectionModel默认选中解决方法

    原文地址:http://379548695.iteye.com/blog/1167234 grid的复选框定义如下:   var sm = new Ext.grid.CheckboxSelection ...

  10. EXTJS中grid的数据特殊显示,不同窗口的数据传递

    //EXTJS中grid的数据特殊显示renderer : function(value, metaData, record, rowIndex, colIndex, store, view) { v ...

随机推荐

  1. #define 的神奇操作

    # define 的神奇操作 一.宏定义中的 #.## 符号的神奇用法 1.1 # 的用法 1.1.1 作用 #表示字符串化操作符(stringification),其作用是将宏定义中的传入参数名转换 ...

  2. Redis的常见应用场景

    缓存.分布式数据共享.setnx分布式锁.incrby全局id进行分库分表.计数器.限流(ip为key,计数超过阈值则返回false).购物车(hash,用户key-商品field-数量value). ...

  3. 【Shell脚本案例】案例1:服务器系统配置初始化

    〇.目录 一.背景 新购买10台服务器,并安装Linux系统 目的:对操作系统进行配置的初始化 二.需求 1.设置时区并同步时间 2.禁用selinux安全机制 3.关闭防火墙(清空防火墙的默认策略, ...

  4. aiohttp、asyncio使用协程增加爬虫效率

    import aiohttp import asyncio import time async def get_requests(url): async with aiohttp.ClientSess ...

  5. 如何通过C#合并Word文档?

    合并Word文档可以快速地将多份编辑好的文档合在一起,避免复制粘贴时遗漏内容,以及耗费不必要的时间,同时,也方便了人们阅读或者对其进行再次修改.例如,在我们进行团队作业的时候,每个人都会有不同的分工, ...

  6. 云原生架构(二)环境搭建(Mac上安装Docker+Kubernetes+Istio一条龙)

    一.背景 Istio 项目由 Google 和 IBM 的团队与 Lyft 的 Envoy 团队合作启动.它已经完全在 GitHub 上公开开发.目前已经是"Service Mesh服务网格 ...

  7. Kubernetes单机创建MySQL+Tomcat演示程序:《Kubernetes权威指南》第一章demo报错踩坑

    引言 最近做边缘计算项目,因为没有基础,所以首先学习Kubernetes.感觉系统的中文入门资料比较少,只找到<Kubernetes权威指南>(龚正.吴治辉等著,下称<指南>) ...

  8. 多表查询两种方法、可视化软件navicat、python操作mysql、pymysql模块

    目录 多表查询的思路 多表查询的两种方法 小知识点补充数说明 可视化软件Navicat 安装教程 数据库常用操作 多表查询练习题 python 操作MySQL pymysql补充说明 Non-grou ...

  9. vue 实现一键复制功能(两种方式)

    方法 一 : <div class="mask-cont"> <p><input id="input" /></p&g ...

  10. JavaScript:操作符:正负号和自增自减及其隐式转换数据类型

    正负号 正号即加号,负号即减号,运算结果同数学意义一样: 对非数字类型进行正负号运算,会隐式转换为数字,再进行运算: 一些特殊的非数字,转换情况同算术运算符: 自增自减 自增即为++,自减即为--. ...