东北赛的一道二等奖题 当时学长想了一个dfs的解法并且通过了 那时自己也有一个bfs的解法没有拿出来 一直没有机会和时ji间xing来验证对错 昨天和队友谈离散化的时候想到了 于是用当时的思路做了一下

题意 : 一个 1e9 * 1e9 的棋盘,有 <=200 个格子是黑的,其他都是白的,问所有白色格子构成的四联通块有多大

因为棋盘规模过大 而黑点是少的 所以想到了离散化

一般离散化保证了离散之后 大小相等关系不变

把普遍的离散化做一下小修改 使相等的点离散化后相等 相邻的点离散化后相邻 有差距的点离散化后缩小差距到1

会发现 这样对黑点以及边界进行离散化之后 如果一个连通块被黑点包围 由于 相邻的点仍旧相邻 所以这个连通块离散化后 大小形状都不变

即 离散化之后 相邻点的骨架结构不变

那么肯定有空间被压缩了 这些被压缩的空间 就是 “有差距的点离散化后缩小差距到1” 这个时候缩小的空间

我称它为虚化空间 由题意 第一行列和最后一行列不同时有点 可以发现 如果虚化空间存在的话 最多只有一个 所有不存在于黑点包围范围的白点 都连接在一起 或许它们可能因为黑点的半包围结构没有缩小 但是它们一定会连接在一起 形成虚化空间

这个虚化空间的规模无法直接求出来(很多别的解法都并非用这种方法 而是压缩矩形)  但是我们知道 出去这个虚化空间 剩下的不是黑点就是被黑点包围的大小不变的白点

那么我们先对xy分别离散化 然后bfs掉虚化空间 剩下的连通块大小都是真实大小 那么虚化空间的size就是n*m-sum(其余联通块) - 黑点个数

bfs虚化空间或许是一个难点 因为并不知道哪个点连接进了这个虚化出来的连通块 但是由于第一行和最后一行不能同时有点这个设定 可以发现棋盘的四个角一定有一个点在虚化空间里面

例如 如果第一行和第一列没有点 那么就满足x最小的点和边界的差距大于1 统一缩小到1 则x为1的点可能存在于虚化空间 只要相对的y也被虚化了

所以 如果一个白点 它的xy不存在黑点拥有 就没有黑点为其支撑骨架 它就会被离散化

orz  终于 也算是给了当时的自己一个交代...

然 这个题有一个坑 它没有说给出的x y 的起点是0还是1

会发现唯一一个可能有说明意味的第一组样例 如果代入起点是0 是说得过去的 ...

但是代入起点是1 也是说得过去的...

de了一下午bug...摔

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<map>
#include<vector>
#include<iostream>
#include<iomanip>
#include<algorithm>
#include<queue>
using namespace std;
#define L long long
L n , m ;
L many ;
L x[205];
L y[205];
struct node{
L pre;
L now;
}a[205];
bool cmp(node a, node b){
return a.pre < b.pre ;
}
L nn ;
L mm ;
bool cmp2(L a, L b){
return a < b ;
}
void lsh1(){
a[0].pre = -1;
a[0].now = -1;
nn = -1;
for(L i = 1; i <= many ; i ++ ){
a[i].pre = x[i];
}
a[many+1].pre = n ;
sort(a+1,a+1+many+1,cmp) ;
for(L i = 1; i <= many+1 ; i ++ ){
if(a[i].pre == a[i-1].pre){
a[i].now = a[i-1].now ;
}
else if(a[i].pre - a[i-1].pre == 1){
a[i].now = a[i-1].now + 1;
}
else {
a[i].now = a[i-1].now + 2;
}
nn = max(nn , a[i].now) ;
}
for(L i = 1; i <= many; i ++ ){
for(L j = 1; j <= many ;j ++ ){
if(x[i] == a[j].pre){
x[i] = a[j].now ;
break;
}
}
}
}
void lsh2(){
a[0].pre = -1;
a[0].now = -1;
mm = -1;
for(L i = 1; i <= many ; i ++ ){
a[i].pre = y[i];
}
a[many+1].pre = m ;
sort(a+1,a+1+many+1,cmp) ;
for(L i = 1; i <= many+1; i ++ ){
if(a[i].pre == a[i-1].pre){
a[i].now = a[i-1].now ;
}
else if(a[i].pre - a[i-1].pre == 1){
a[i].now = a[i-1].now + 1;
}
else {
a[i].now = a[i-1].now + 2;
}
mm = max(mm , a[i].now) ;
}
for(L i = 1; i <= many; i ++ ){
for(L j = 1; j <= many+1 ;j ++ ){
if(y[i] == a[j].pre){
y[i] = a[j].now ;
break;
}
}
}
}
bool vis[500][500] ;
L ans[500] ;
bool check(L x,L y){
if(x >= 0 &&x < nn && y >=0 && y < mm){
if(vis[x][y])return true;
}
return false ;
}
L dx[4] = {1,-1,0,0};
L dy[4] = {0,0,1,-1};
L bfs(L x,L y){
queue<L >que;
que.push(x);
que.push(y);
vis[x][y]=false;
L res = 1 ;
while(!que.empty()){
L x = que.front();que.pop();
L y = que.front();que.pop();
for(L i = 0; i < 4; i ++ ){
L xx = dx[i] + x;
L yy = dy[i] + y;
if(check(xx,yy)){
que.push(xx);
que.push(yy);
vis[xx][yy]=false ;
res ++ ;
}
}
}
return res ;
}
int main(){
L t ;
scanf("%lld",&t);
L cas = 1 ;
while(t-- ){
scanf("%lld%lld",&n,&m) ;
scanf("%lld",&many) ;
bool qsx = false ;
bool qsy = false ;
for(L i = 1; i <= many ; i ++ ){
scanf("%lld%lld",&x[i],&y[i]) ;
x[i] -- ;
y[i] -- ;
if(x[i] == 0)qsx = true ;
if(y[i] == 0)qsy = true ;
}
memset(vis, true , sizeof(vis)) ;
lsh1(); lsh2();
for(L i = 1; i <= many ; i ++ ){
vis[x[i]][y[i]] = false ;
}
L cnt = 0;
L z ;
if(qsx){
if(qsy){
z = bfs(nn-1,mm-1);
}
else z = bfs(nn-1,0) ;
}
else {
if(qsy){
z = bfs(0,mm-1) ;
}
else z = bfs(0,0) ;
}
cnt ++ ;
ans[cnt] = z;
L sum = many ;
for(L i = 0; i < nn ; i ++ ){
for(L j = 0; j < mm ; j ++ ){
if(vis[i][j]) {
L dd = bfs(i,j) ;
sum += dd;
cnt ++ ;
ans[cnt] = dd ;
}
}
}
ans[1] = n*m-sum;
sort(ans+1,ans+1+cnt,cmp2);
printf("Case #%lld:\n",cas++);
printf("%lld\n",cnt);
for(int i = 1; i <= cnt ;i ++ ){
printf("%lld",ans[i]);
if(i==cnt)printf("\n");
else printf(" ");
}
}
}

  

HDU 5925 离散化的更多相关文章

  1. Coconuts HDU - 5925 (二维离散化求连通块的个数以及大小)

    题目链接: D - Coconuts  HDU - 5925 题目大意:首先是T组测试样例,然后给你n*m的矩阵,原先矩阵里面都是白色的点,然后再输入k个黑色的点.这k个黑色的点可能会使得原先白色的点 ...

  2. R - Weak Pair HDU - 5877 离散化+权值线段树+dfs序 区间种类数

    R - Weak Pair HDU - 5877 离散化+权值线段树 这个题目的初步想法,首先用dfs序建一颗树,然后判断对于每一个节点进行遍历,判断他的子节点和他相乘是不是小于等于k, 这么暴力的算 ...

  3. HDU 5925 Coconuts 【离散化+BFS】 (2016CCPC东北地区大学生程序设计竞赛)

    Coconuts Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  4. HDU 5925 Coconuts 离散化

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5925 Coconuts Time Limit: 9000/4500 MS (Java/Others) ...

  5. Coconuts HDU - 5925 二维离散化 自闭了

    TanBig, a friend of Mr. Frog, likes eating very much, so he always has dreams about eating. One day, ...

  6. hdu 5925 Coconuts 离散化+dfs

    Coconuts Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem ...

  7. HDU 2836 (离散化DP+区间优化)

    Reference:http://www.cnblogs.com/wuyiqi/archive/2012/03/28/2420916.html 题目链接: http://acm.hdu.edu.cn/ ...

  8. (转)hdu 3436Queue-jumpers--splay+离散化

    dalao博客 http://acm.hdu.edu.cn/showproblem.php?pid=3436 题意:初始排列1到N,现在要你实现3种操作: 将x插入到队头去 询问x当前的位置 询问第x ...

  9. hdu 5009 离散化

    http://acm.hdu.edu.cn/showproblem.php?pid=5009 有一段序列,涂连续一段子序列的代价为该子序列出现不同数字个数的平方,求最小代价涂完整个序列. ai有10^ ...

随机推荐

  1. node.js的安装与第一个hello world、node.js的初始化

    1.下载node.js文件 2.windows下点击安装  重复下一步即可 3.编辑工具  EditPlus编辑器 4.新建保存目录的文件夹,并新建一个文本文档 5.打开EditPlus编辑器  打开 ...

  2. 【BZOJ1820】[JSOI2010]Express Service 快递服务 暴力DP

    [BZOJ1820][JSOI2010]Express Service 快递服务 Description 「飞奔」快递公司成立之后,已经分别与市内许多中小企业公司签订邮件收送服务契约.由于有些公司是在 ...

  3. 【BZOJ2793】[Poi2012]Vouchers 调和级数

    [BZOJ2793][Poi2012]Vouchers Description 考虑正整数集合,现在有n组人依次来取数,假设第i组来了x人,他们每个取的数一定是x的倍数,并且是还剩下的最小的x个.正整 ...

  4. 1154 回文串划分(DP+Manacher)

    1154 回文串划分 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 有一个字符串S,求S最少可以被划分为多少个回文串. 例如:abbaabaa,有多种划分方式. ...

  5. Python中MRO

    MRO(方法解析顺序) 当有多重继承时,基于“从左到右,深度优先原则”: class CommonBase(): def Method(self): print('CommonBase') class ...

  6. 用SQL语句生成唯一标识

    以前都是在代码中生成GUID值,然后保存到数据库中去,今天发现用sql也能生成GUID值,觉得很新奇,所以记下来. sellect newid();  //得到的即为GUID值 此sql内置函数返回的 ...

  7. go build说明

    go build命令用于编译我们指定的源码文件或代码包以及它们的依赖包. 例如,如果我们在执行go build命令时不后跟任何代码包,那么命令将试图编译当前目录所对应的代码包.例如,我们想编译goc2 ...

  8. Centos7安装zookeeper

    1.进入/opt cd /opt 2.下载 zookeeper-3.4.10.tar.gz: wget https://mirrors.tuna.tsinghua.edu.cn/apache/zook ...

  9. python面向对象(一)

    什么是面向对象的程序设计及为什么要有它 面向过程的程序设计:核心是过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式的思维方式. ...

  10. Ensemble learning(集成学习)

    定义 集成学习是一种机器学习范式,其中多个学习器被训练来解决相同的问题. 这与试图从训练数据中学习一个假设的普通机器学习方法相反,集成方法尝试构造一组假设并将它们结合使用. 一个集合包含一些通常被称为 ...