正题

题目链接:https://www.luogu.com.cn/problem/P7295


题目大意

给出\(n*m\)的网格,每个格子上有字母,相同字母的四联通相邻格子为连通,每次询问一个子矩阵求连通块个数。

\(1\leq n,m,q\leq 1000\)


解题思路

首先一张连通的平面图有欧拉公式

\[V+F=E+2
\]

其中\(V,E,F\)分别表示点数,边数,区域个数(对偶图点数)。

然后不连通的对偶图会共用一个无界域,设为\(C\)个连通块,无界域会重复统计\(C-1\)次,然后联立得

\[V+F-E=C+1
\]

然后考虑怎么用这个求,首先是\(V,E\),这个很容易搞,\(V\)直接计算,\(E\)用二维前缀和算就好了。

主要是\(F\)怎么搞,先构出不严格的对偶图(就是每个格子边上的点当做点),然后\(F\)就是对偶图的连通块数。

对于整张图的每个连通块,我们选择任意一个点标记,然后记录每个点对应连通块的标记点,然后直接二维前缀和统计连通块内的标记点个数,然后枚举边界减去边上不完整被统计的的连通块最后加上无界域就好了。

时间复杂度\(O(nm+q(n+m))\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1100;
const int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
int n,m,q,E[2][N][N],mx[N][N],my[N][N],F[N][N];
char s[N][N];bool v[N][N];
bool edg(int x,int y,int zx,int zy){
if(zx<0||zy<0||zx>n||zy>m)return 0;
if(zx>0&&zx<n&&zy==y+1)return (s[x][y+1]!=s[x+1][y+1]);
if(zx>0&&zx<n&&zy==y-1)return (s[x][y]!=s[x+1][y]);
if(zy>0&&zy<m&&zx==x+1)return (s[x+1][y]!=s[x+1][y+1]);
if(zy>0&&zy<m&&zx==x-1)return (s[x][y]!=s[x][y+1]);
return 1;
}
void dfs(int x,int y){
if(x==1&&y==4)
x++,x--;
if(v[x][y])return;v[x][y]=1;
for(int k=0;k<4;k++){
int zx=x+dx[k],zy=y+dy[k];
if(edg(x,y,zx,zy)){
mx[zx][zy]=mx[x][y];
my[zx][zy]=my[x][y];
dfs(zx,zy);
}
}
return;
}
#define Get(F,x1,y1,x2,y2) (F[x2][y2]-((x1)?F[x1-1][y2]:0)-((y1)?F[x2][y1-1]:0)+(((x1)&&(y1))?F[x1-1][y1-1]:0))
int check(int x,int y,int x1,int y1,int x2,int y2){
if(!v[x][y]&&x>=x1&&x<=x2&&y>=y1&&y<=y2)
{v[x][y]=1;return 1;}
return 0;
}
int main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
E[0][i][j]=E[0][i-1][j]+E[0][i][j-1]-E[0][i-1][j-1];
E[1][i][j]=E[1][i-1][j]+E[1][i][j-1]-E[1][i-1][j-1];
if(s[i][j]==s[i][j+1])E[0][i][j]++;
if(s[i][j]==s[i+1][j])E[1][i][j]++;
}
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
if(!v[i][j]){
mx[i][j]=i;my[i][j]=j;
F[i][j]++;dfs(i,j);
}
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++)
F[i][j]+=(i?F[i-1][j]:0)+(j?F[i][j-1]:0)-((i&&j)?F[i-1][j-1]:0);
memset(v,0,sizeof(v));
while(q--){
int x1,y1,x2,y2,ans=0;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
ans+=(x2-x1+1)*(y2-y1+1);
if(y1!=y2)ans-=Get(E[0],x1,y1,x2,y2-1);
if(x1!=x2)ans-=Get(E[1],x1,y1,x2-1,y2);
x1--;y1--;ans+=Get(F,x1,y1,x2,y2);
for(int i=x1;i<=x2;i++){
ans-=check(mx[i][y1],my[i][y1],x1,y1,x2,y2);
ans-=check(mx[i][y2],my[i][y2],x1,y1,x2,y2);
}
for(int i=y1;i<=y2;i++){
ans-=check(mx[x1][i],my[x1][i],x1,y1,x2,y2);
ans-=check(mx[x2][i],my[x2][i],x1,y1,x2,y2);
}
printf("%d\n",ans);
for(int i=x1;i<=x2;i++){
v[mx[i][y1]][my[i][y1]]=0;
v[mx[i][y2]][my[i][y2]]=0;
}
for(int i=y1;i<=y2;i++){
v[mx[x1][i]][my[x1][i]]=0;
v[mx[x2][i]][my[x2][i]]=0;
}
}
return 0;
}

P7295-[USACO21JAN]Paint by Letters P【平面图欧拉公式】的更多相关文章

  1. ZOJ 2589 Circles(平面图欧拉公式)

    [题目链接] http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2589 [题目大意] 给出一些圆,问这些圆可以把平面分为几个部 ...

  2. POJ--2284--That Nice Euler Circuit【平面图欧拉公式】

    链接:id=2284">http://poj.org/problem?id=2284 题意:一个自己主动绘图的机器在纸上(无限大)绘图,笔尖从不离开纸,有n个指令,每一个指令是一个坐标 ...

  3. android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索

    我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...

  4. Android ListView A~Z快速索引(改进版)

    上一篇文章虽然实现了ListView 快速索引的效果,但是有一个小小的Bug.这个Bug我在前面也说了,这篇文章就来解决这个Bug. 我研究的时候发现只要showBg值为true,中间的字母就显示,而 ...

  5. 实现ListView A~Z快速索引

    ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法. 实现步骤: 1.自定义一个名叫SlideBar 的View. 2.在布局文件中加入这个 ...

  6. Android通讯录管理(获取联系人、通话记录、短信消息)

    前言:前阵子主要是记录了如何对联系人的一些操作,比如搜索,全选.反选和删除等在实际开发中可能需要实现的功能,本篇博客是小巫从一个别人开源的一个项目抽取出来的部分内容,把它给简化出来,可以让需要的朋友清 ...

  7. ZOJ 3781 Paint the Grid Reloaded(BFS)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3781 Leo has a grid with N rows an ...

  8. poj2284 That Nice Euler Circuit(欧拉公式)

    题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k( ...

  9. POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)

                                                          That Nice Euler Circuit Time Limit: 3000MS   M ...

随机推荐

  1. 在Asp .net core 中通过属性映射实现动态排序和数据塑形

    目录 属性映射服务实现 动态排序 数据塑形 属性映射服务实现 public class PropertyMappingValue { public IEnumerable<string> ...

  2. Dos 获取网络的命令

    Netsh mbn 命令 https://docs.microsoft.com/zh-cn/windows-server/networking/technologies/netsh/netsh-mbn ...

  3. C#基础知识---?为何物

    一. 可空类型修饰符(?)引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; 是正确的,int i=null; 编译器就会报错.可空类型的出现, ...

  4. 【mysql】截取查询分析

    1. 慢查询日志 1.1 是什么 (1)MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long_query_time值的SQL ...

  5. HttpClient 4.3教程-前言

    前言 Http协议应该是互联网中最重要的协议.持续增长的web服务.可联网的家用电器等都在继承并拓展着Http协议,向着浏览器之外的方向发展. 虽然jdk中的java.net包中提供了一些基本的方法, ...

  6. LeetCoded第21题题解--合并两个有序链表

    21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出 ...

  7. js之window对象(慕课网学习笔记)

    javaScript定义了一个变量一个函数都会变成window中的一个成员 var a=1; alert(window.a) //会输出a的值 window基础 创建窗口.调整窗口.移动窗口.关闭窗口 ...

  8. TNN iOS非图像模型入门

    注:本文同步发布于微信公众号:stringwu的互联网杂谈TNN iOS 非图像模型入门指南 1 背景 TNN是腾讯优图实验室开源的高性能.轻量级神经网络推理框架TNN,github上也有比较详细的例 ...

  9. 浅析mybatis中${}和#{}取值区别

    mybatis作为一个轻量级的ORM框架,应用广泛,其上手使用也比较简单:一个成熟的框架,必然有精巧的设计,值得学习. 在使用mybatis框架时,在sql语句中获取传入的参数有如下两种方式: ${p ...

  10. ubuntu14.04 安装MySQL 5.7

    ubuntu14.04 默认在线安装MySQL 5.5 1) wget http://dev.mysql.com/get/mysql-apt-config_0.7.3-1_all.deb 2) dpk ...