P7295-[USACO21JAN]Paint by Letters P【平面图欧拉公式】
正题
题目链接:https://www.luogu.com.cn/problem/P7295
题目大意
给出\(n*m\)的网格,每个格子上有字母,相同字母的四联通相邻格子为连通,每次询问一个子矩阵求连通块个数。
\(1\leq n,m,q\leq 1000\)
解题思路
首先一张连通的平面图有欧拉公式
\]
其中\(V,E,F\)分别表示点数,边数,区域个数(对偶图点数)。
然后不连通的对偶图会共用一个无界域,设为\(C\)个连通块,无界域会重复统计\(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【平面图欧拉公式】的更多相关文章
- ZOJ 2589 Circles(平面图欧拉公式)
[题目链接] http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2589 [题目大意] 给出一些圆,问这些圆可以把平面分为几个部 ...
- POJ--2284--That Nice Euler Circuit【平面图欧拉公式】
链接:id=2284">http://poj.org/problem?id=2284 题意:一个自己主动绘图的机器在纸上(无限大)绘图,笔尖从不离开纸,有n个指令,每一个指令是一个坐标 ...
- android自定义View之仿通讯录侧边栏滑动,实现A-Z字母检索
我们的手机通讯录一般都有这样的效果,如下图: OK,这种效果大家都见得多了,基本上所有的android手机通讯录都有这样的效果.那我们今天就来看看这个效果该怎么实现. 一.概述 1.页面功能分析 整体 ...
- Android ListView A~Z快速索引(改进版)
上一篇文章虽然实现了ListView 快速索引的效果,但是有一个小小的Bug.这个Bug我在前面也说了,这篇文章就来解决这个Bug. 我研究的时候发现只要showBg值为true,中间的字母就显示,而 ...
- 实现ListView A~Z快速索引
ListView A~Z快速索引这种效果在通信录和城市列表中经常看到,方便用户查找,是一种增加用户体验的好方法. 实现步骤: 1.自定义一个名叫SlideBar 的View. 2.在布局文件中加入这个 ...
- Android通讯录管理(获取联系人、通话记录、短信消息)
前言:前阵子主要是记录了如何对联系人的一些操作,比如搜索,全选.反选和删除等在实际开发中可能需要实现的功能,本篇博客是小巫从一个别人开源的一个项目抽取出来的部分内容,把它给简化出来,可以让需要的朋友清 ...
- 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 ...
- poj2284 That Nice Euler Circuit(欧拉公式)
题目链接:poj2284 That Nice Euler Circuit 欧拉公式:如果G是一个阶为n,边数为m且含有r个区域的连通平面图,则有恒等式:n-m+r=2. 欧拉公式的推广: 对于具有k( ...
- POJ2284 That Nice Euler Circuit (欧拉公式)(计算几何 线段相交问题)
That Nice Euler Circuit Time Limit: 3000MS M ...
随机推荐
- SpringBoot和mybatis整合报错:Caused by: org.apache.ibatis.builder.BuilderException: Error creating document instance. Cause: org.xml.sax.SAXParseException; lineNumber: 152; columnNumber: 10; 元素类型为 "mapper"
很明显,报错是xml有问题,于是去检查,发现: 由于粗心,保存的时候,按的太频繁,多按了个s在里面,导致启动报错!
- PHP随手记2--获取随机n位不重复字符
定义一个函数返回26英文字母中n位不重复随机字符 基本思路是利用内置函数生成随机数,取出该位置字母之后将其删除,再进行下一次随机,最后实现字符串拼接就ok! 代码很简单,通俗易懂,直接上代码吧: 1 ...
- 0x800b010a 证书
无论是装微软的什么应用,只要报这个错误,下载这个证书: http://download.microsoft.com/download/2/4/8/248D8A62-FCCD-475C-85E7-6ED ...
- 【java虚拟机】垃圾回收机制详解
作者:平凡希 原文地址:https://www.cnblogs.com/xiaoxi/p/6486852.html 一.为什么需要垃圾回收 如果不进行垃圾回收,内存迟早都会被消耗空,因为我们在不断的分 ...
- 09.SpringMVC之类型转换
一. 类型转换器 前端传入的值,从表单中传入的值,都是字符串或者是字符串数组的形式传入的,在后端需要进行手动的转换类型,然后才能正确的使用. 框架一般对常见的数据类型的转换进行了封装提供,如字符串转换 ...
- DNS地址列表
DNS测试工具(DNSBench):https://www.grc.com/dns/benchmark.htm DNS列表收集: Google DNS [URL]https://developers. ...
- IPython中也要保持优雅(DRY原则)
What is IPython? IPython provides a rich architecture for interactive computing with: A powerful int ...
- php常用的函数
addslashes: 字符串加入斜线.bin2hex: 二进位转成十六进位.chop: 去除连续空白.chr: 返回序数值的字符.chunk_split: 将字符串分成小段.convert_cyr_ ...
- 【Azure 应用服务】App Service For Windows 环境中部署Python站点后,如何继续访问静态资源文件呢(Serving Static Files)?
问题描述 当创建一个App Service 后,运行时环境和版本选择Windows 和 Python 3.6. 登录Kudu 站点查看,默认的文件有 web.config, hostingstart- ...
- NX二次开发-创建NX9 NXOpenCPP Wizard开发向导模板
这篇文章,我在CSDN,在唐工论坛都发过.http://www.nxopen.cn/forum.php?mod=viewthread&tid=2039&highlight=NX9 博客 ...