「HNSDFZ暑期集训 测试1」「LuoguT36488」 连连看
题目描述
给定一个n × m的矩形地图,每个各自上可能为空,可能有牌,牌上有一个数字。
对于两张同样数字的牌,如果我们可以在地图上用不超过三根水平或竖直,在地图界内,且不经过其他牌的线段将两张牌连起来,那么我们这一对牌是可以被消去的。
比如下图中,两张1可以被消去,但是2和3都不能被消去。 
现在给出一个n × m的连连看地图,其中有2k张牌,保证每张牌上的数字都在[1, k]范围内,且每个数字都只会出现两次,问目前有多少对牌是可以消去的。
输入输出格式
输入格式:
输入第一行三个正整数n, m, k,分别代表地图的长,宽以及牌的对数。
接下来k行每行四个正整数x1 , y1 , x2 , y2,表示数字为k的两张牌的位置。
输出格式:
输出仅一行一个整数,表示当前可以消去的牌的对数
输入输出样例
说明
30%的数据 n, m≤ 20,k<=min(3, ⌊ n*m/2 ⌋)
接下来30%的数据 n, m≤ 100,k<=min(100, ⌊ n*m/2 ⌋)
接下来30%的数据 n, m≤ 1000,k<=min(5000, ⌊ n*m/2 ⌋)
题解
考虑数据范围很小,我们可以做各种n方操作。
读入的同时把相应坐标标记
flag[ i ] [ j ]=1;
套两个for循环,分别求横排上的前缀和 及竖排上的前缀和
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
ss[i][j]=ss[i-1][j]+tu[i][j],
hs[i][j]=hs[i][j-1]+tu[i][j];
对于每组牌:
我们把一张牌分别向上下左右暴力走,走到边界或障碍就停,经过的点就标记。(画十字)
|____________|
| O |
| | O |
| | |
| O——O————O|
| | |
| | |
| O | |
|______|_____|
然后把第二张牌也上下左右暴力走,同样经过则标记。如果有到被标记过的点,说明路线相交了,这对牌可消,flag=1
若未相交:
从1~n枚举横坐标j,如果这一段(< x1 , j >点到 < x2 , j >点)上的区间和为0
且< x1 , j >点和< x2 , j >点被标记过(画十字的时候经历过)的话(用前缀和O(1)查询)
则这一段没有障碍,可以连线,flag=1
从1~n枚举纵坐标i,如果< i , y1 >点到< i , y2 >上的区间和为0,则可连,flag=1
最后如果flag为1,则ans++
代码://考场代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
inline int read()//快读
{
char ch=getchar();
int x=;bool s=;
while(ch<''||ch>''){if(ch=='-')s=;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-;ch=getchar();}
return s?x:-x;
}
int lx[],ly[],rx[],ry[];
int ss[][];
int hs[][];
bool tu[][];
bool sf[][];
int main()
{
int n=read(),m=read(),k=read();
for(int i=;i<=k;++i)
{
lx[i]=read(),
ly[i]=read(),
rx[i]=read(),
ry[i]=read();
tu[lx[i]][ly[i]]=;
tu[rx[i]][ry[i]]=;//标记
}
for(int i=;i<=n+;++i)
tu[i][]=tu[i][m+]=;
for(int i=;i<=m+;++i)
tu[][i]=tu[n+][i]=;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
ss[i][j]=ss[i-][j]+tu[i][j],
hs[i][j]=hs[i][j-]+tu[i][j];//前缀和
int ans=;
for(int c=;c<=k;++c)
{
int flag=;
memset(sf,,sizeof(sf));
//以下一大堆为画十字
tu[lx[c]][ly[c]]=;
tu[rx[c]][ry[c]]=;//便于之后操作
int x=lx[c],y=ly[c];
int l,r,u,d;
while(!tu[x][y]){sf[x--][y]=;}
u=x+;
x=lx[c]+,y=ly[c];
while(!tu[x][y]){sf[x++][y]=;}
d=x-;
x=lx[c],y=ly[c]-;
while(!tu[x][y]){sf[x][y--]=;}
l=y+;
x=lx[c],y=ly[c]+;
while(!tu[x][y]){sf[x][y++]=;}
r=y-;
x=rx[c],y=ry[c];
while(!tu[x][y]){if(sf[x][y])flag++;sf[x--][y]=;}
u=max(u,x+);
x=rx[c]+,y=ry[c];
while(!tu[x][y]){if(sf[x][y])flag++;sf[x++][y]=;}
d=min(d,x-);
x=rx[c],y=ry[c]-;
while(!tu[x][y]){if(sf[x][y])flag++;sf[x][y--]=;}
l=max(l,y+);
x=rx[c],y=ry[c]+;
while(!tu[x][y]){if(sf[x][y])flag++;sf[x][y++]=;}
r=min(r,y-);
//画十字结束
if(!flag)
{
int zx=lx[c],zy=ly[c],yx=rx[c],yy=ry[c];
if(zx>yx)swap(zx,yx);
if(zy>yy)swap(zy,yy);
for(int i=u;i<=d;++i)//枚举横坐标
if(hs[i][yy]-hs[i][zy-]==)flag++;
for(int j=l;j<=r;++j)//枚举纵坐标
if(ss[yx][j]-ss[zx-][j]==)flag++;
}
if(flag)ans++;
tu[lx[c]][ly[c]]=;
tu[rx[c]][ry[c]]=;//复原
//cout<<flag<<endl;
}
cout<<ans;//强大怪!!!
return ;
}
//强大怪!!!(滑稽
「HNSDFZ暑期集训 测试1」「LuoguT36488」 连连看的更多相关文章
- 「HNSDFZ暑期集训 测试1」「LuoguT36485」 括号(贪心
Description 给定一个由左括号'('和右括号')'组成的字符串s,其中第i个括号的权值为ai. 我们定义一个括号序列t为合法括号序列,当且仅当满足下列条件之一: 1.t为空串 2.t=(A) ...
- loj #6046. 「雅礼集训 2017 Day8」爷
#6046. 「雅礼集训 2017 Day8」爷 题目描述 如果你对山口丁和 G&P 没有兴趣,可以无视题目背景,因为你估计看不懂 …… 在第 63 回战车道全国高中生大赛中,军神西住美穗带领 ...
- LOJ_6045_「雅礼集训 2017 Day8」价 _最小割
LOJ_6045_「雅礼集训 2017 Day8」价 _最小割 描述: 有$n$种减肥药,$n$种药材,每种减肥药有一些对应的药材和一个收益. 假设选择吃下$K$种减肥药,那么需要这$K$种减肥药包含 ...
- 「雅礼集训 2017 Day7」事情的相似度
「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...
- 「雅礼集训 2017 Day2」解题报告
「雅礼集训 2017 Day2」水箱 我怎么知道这种题目都能构造树形结构. 根据高度构造一棵树,在树上倍增找到最大的小于约束条件高度的隔板,开一个 \(vector\) 记录一下,然后对于每个 \(v ...
- 「雅礼集训 2017 Day1」 解题报告
「雅礼集训 2017 Day1」市场 挺神仙的一题.涉及区间加.区间除.区间最小值和区间和.虽然标算就是暴力,但是复杂度是有保证的. 我们知道如果线段树上的一个结点,\(max=min\) 或者 \( ...
- [LOJ 6031]「雅礼集训 2017 Day1」字符串
[LOJ 6031] 「雅礼集训 2017 Day1」字符串 题意 给定一个长度为 \(n\) 的字符串 \(s\), \(m\) 对 \((l_i,r_i)\), 回答 \(q\) 个询问. 每个询 ...
- [LOJ 6030]「雅礼集训 2017 Day1」矩阵
[LOJ 6030] 「雅礼集训 2017 Day1」矩阵 题意 给定一个 \(n\times n\) 的 01 矩阵, 每次操作可以将一行转置后赋值给某一列, 问最少几次操作能让矩阵全为 1. 无解 ...
- [LOJ 6029]「雅礼集训 2017 Day1」市场
[LOJ 6029] 「雅礼集训 2017 Day1」市场 题意 给定一个长度为 \(n\) 的数列(从 \(0\) 开始标号), 要求执行 \(q\) 次操作, 每次操作为如下四种操作之一: 1 l ...
随机推荐
- C# 编程中的堆栈(Stack)和队列(Queue)
一.什么是堆?(Heap) 堆是无序的,是一片不连续的内存域,由用户自己来控制和释放,如果用户自己不释放的话,当内存达到一定的特定值时,通过垃圾回收器(GC)来回收. 是程序运行期 ...
- Heavy Transportation(最短路)
poj 1797 ——Heavy Transportation 思路: 这道题我们可以采用类似于求最短路径的方法,用一种新的“松弛操作”去取代原本的方法. 我们可以记录d[u]为运送货物到点j时最大可 ...
- 【Todo】已经打开的页面需要清掉的坑
下面是当前我浏览器里面打开的技术文章.需要清掉.一个坑一个坑地填吧. 微信文件传输里面也有几篇12.6号的<Akuna Capital电面面经><2016最流行的Java EE服务器 ...
- C#语法复习3
第七章 类与继承 1.虽然派生类不能删除基类的的任何成员,但我们可以利用在派生类当中声明与基类成员名称相同的成员来屏蔽基类成员.这叫 覆盖. 一种是隐式屏蔽.一种是显式屏蔽.所谓 显式就是 加上一个n ...
- yii使用CUploadedFile上传文件
一.前端代码 Html代码 <form action="<?php echo $this->createUrl('/upload/default/upload/');? ...
- 【转载】一些VS2013的使用技巧
1. Peek View 可以在不新建TAB的情况下快速查看.编辑一个函数的代码. 用法:在光标移至某个函数下,按下alt+F12. 然后在Peek窗口里可以继续按alt+F12.然后按ctrl+al ...
- ftk学习记(combox篇)
[声明:版权全部,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 上一篇文章谈到了多窗体,还是依照约定看一下效果是什么样的. 假设大家细心一点.就会发现窗体中的l ...
- Animated progress view with CAGradientLayer(带翻译)
Animated progress view with CAGradientLayer(带翻译) Modern software design is getting flatter and thin ...
- 跨平台C++:(前言)正确打开C++的方式
接触C++已经十五年了...但是对于C++而言,我至今是个门外汉,不是谦虚,而是确实不得其门而入. 历程是这样的—— 大学考研要考C++,就自学了.研没考上,C++算是学了,准确的说是C++的语法,以 ...
- CXF、Spring整合的SOAP Web Service服务端
1.建工程,导入CXFjar包 2.服务接口 package com.cxf.soap; import java.util.List; import javax.jws.WebService; @We ...