「JOI 2017 Final」JOIOI 王国

题目描述

题目译自 JOI 2017 Final T3「 JOIOI 王国 / The Kingdom of JOIOI」

JOIOI 王国是一个 HHH 行 WWW 列的长方形网格,每个 1×11\times 11×1 的子网格都是一个正方形的小区块。为了提高管理效率,我们决定把整个国家划分成两个省 JOI 和 IOI 。

我们定义,两个同省的区块互相连接,意为从一个区块出发,不用穿过任何一个不同省的区块,就可以移动到另一个区块。有公共边的区块间可以任意移动。

我们不希望划分得过于复杂,因此划分方案需满足以下条件:

区块不能被分割为两半,一半属 JOI 省,一半属 IOI 省。

每个省必须包含至少一个区块,每个区块也必须属于且只属于其中一个省。

同省的任意两个小区块互相连接。

对于每一行/列,如果我们将这一行/列单独取出,这一行/列里同省的任意两个区块互相连接。这一行/列内的所有区块可以全部属于一个省。

现给出所有区块的海拔,第 iii 行第 jjj 列的区块的海拔为 Ai,jA_{i,j}A​i,j​​。设 JOI 省内各区块海拔的极差(最大值减去最小值) 为 RJOIR_{JOI}R​JOI​​,IOI 省内各区块海拔的极差为 RIOIR_{IOI}R​IOI​​。在划分后,省内的交流有望更加活跃。但如果两个区块的海拔差太大,两地间的交通会很不方便。 因此,理想的划分方案是 max(RJOI,RIOI)\max(R_{JOI}, R_{IOI})max(R​JOI​​,R​IOI​​) 尽可能小。

你的任务是求出 max(RJOI,RIOI)\max(R_{JOI}, R_{IOI})max(R​JOI​​,R​IOI​​) 至少为多大。

输入格式

第一行,两个整数 H,WH,WH,W,用空格分隔。

在接下来的 HHH 行中,第 iii 行有 WWW 个整数 Ai,1,Ai,2,…,Ai,WA_{i,1}, A_{i, 2}, \ldots, A_{i, W}A​i,1​​,A​i,2​​,…,A​i,W​​,用空格分隔。

输入的所有数的含义见题目描述。

输出格式

一行,一个整数,表示 max(RJOI,RIOI)\max(R_{JOI}, R_{IOI})max(R​JOI​​,R​IOI​​) 可能的最小值。

样例

样例输入 1

4 4

1 12 6 11

11 10 2 14

10 1 9 20

4 17 19 10

样例输出 1

11

样例输入 2

8 6

23 23 10 11 16 21

15 26 19 28 19 20

25 26 28 16 15 11

11 8 19 11 15 24

14 19 15 14 24 11

10 8 11 7 6 14

23 5 19 23 17 17

18 11 21 14 20 16

样例输出 2

18

数据范围与提示

对于 15%15\%15% 的数据,H,W⩽10H, W\leqslant 10H,W⩽10。

对于另外 45%45\%45% 的数据,H,W⩽200H, W\leqslant 200H,W⩽200。

对于所有数据,2⩽H,W⩽2000,Ai,j⩽109(1⩽i⩽H,1⩽j⩽W)2\leqslant H, W\leqslant 2000, A_{i,j}\leqslant 10^9(1\leqslant i\leqslant H, 1\leqslant j\leqslant W)2⩽H,W⩽2000,A​i,j​​⩽10​9​​(1⩽i⩽H,1⩽j⩽W)。

【及其不正经的题解】

不想看的往后翻(我知道你们就只看代码)

咳咳,这道题是是吕神考试的T2。T1是道思维量挺高的贪心,T3是道期望dp,我都懒得做(我绝对不会告诉你是因为我太菜了),所以我开始看T2。一共大概写了3个小时,200行后,我成功A掉了样例,正当我高兴的手舞足蹈,以为要在吕神的考试上切题时,我随手写了个小数据,结果竟然hack掉了我的代码!(我怎么那么欠)我的心态就崩了。怀着忐忑的心情,我把代码交了上去,结果得了6分(旁边低一年级的小学弟交了个错的dfs,拿了个8分)

关键是,我(已删)写的是正解!

我那獐头鼠目百拙千丑鹰头雀脑鹄面鸠形不堪入目鸢肩豺目乌面鹄形的代码就暂且不放在这里了,有想看的可以私聊。下面简单介绍一下我的思路

【题解】

首先,要看懂这题,必须先看懂这句话“对于每一行/列,如果我们将这一行/列单独取出,这一行/列里同省的任意两个区块互相连接。这一行/列内的所有区块可以全部属于一个省”。

这句话是什么意思呢?

我们先来看三个图(A代表joi,B代表ioi)

(1)

AAAAAAAAAB

AAAAAABBBB

AABBBBBBBB

AAAAABBBBB

AAAAAAAABB

(2)

AAAAAAAAAA

AAAAAAAAAA

AAAABAAAAA

AABBBBAAAA

BBBBBBBBAA

(3)

AAAAAAAABB

AAAAAAABBB

AAAAAABBBB

AABBBBBBBB

ABBBBBBBBB

如果你读懂了上面的话,就知道上面三个图中,只有图3是合法的。也就是说,你在切分两个国家时,只能画一条单调的线。

但是一个国家既可以左右延伸,也可以上下延伸。这怎么办呢?

我们可以先写从左开始,向右延伸的方法,然后分别把图旋转90,180,270度,这样四种情况就都齐了。但得到了图该怎样做?

我们注意一下这道题的输出是什么:max(R​JOI​​,R​IOI​​) 尽可能小。最小值最大?没错,就是你二分,出来吧!

我们首先得到最大值与最小值,并且答案肯定小于最大值-最小值。注意(敲黑板),重点来了!

假定最大值在joi,最小值在ioi,我们从左上角逐行扫荡,每行的joi王国方格数不超过上一行的(不考虑每行方格数不少于上一行的这种情况)

二分一个答案,只要当前二分中点mid大于等于这个方格与最大值就选它去构造ioi王国,然后再去判断ioi王国中的元素是不是都满足条件

只要不符合就跳转到下一行。

想到了这里,这题就基本结束了。是不是很神奇呢?

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
int n,m,a[][],ans=INF,maxn=-INF,minn=INF;
inline int read()//小小的读入优化,可以不写
{
int x=,f=; char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=ch-''+(x<<)+(x<<);
return x*f;
} int MAX(int a,int b)
{
if(a>b) return a;
if(a<=b) return b;
} int MIN(int a,int b)//手打好像快一点
{
if(a<b) return a;
if(a>=b) return b;
} void turn()//旋转90度
{
for(int i=;i<=n;i++)
for(int j=;j<=m/;j++)
swap(a[i][j],a[i][m-j+]);
} void choose()//选择
{
for(int i=;i<=n/;i++)
for(int j=;j<=m;j++)
swap(a[i][j],a[n-i+][j]);
} bool check(int mid)
{
int f=m+;
for(int i=;i<=n;i++)
{
int t=;
for(int j=;j<=min(f,m);j++)
if(maxn-a[i][j]<=mid) t=max(t,j);//找i行的最大延伸
else break;
f=t;
for(int j=t+;j<=m;j++)
if(a[i][j]-minn>mid) return ;//判断满足条件
}
return ;
} int find_ans()//二分
{
int l=,r=maxn-minn+;
while(l<=r)
{
int mid=(l+r)>>;
if(check(mid)) r=mid-;
else l=mid+;
}
return l;
} void find_ans2()//枚举4种情况
{
ans=min(ans,find_ans());
turn();
ans=min(ans,find_ans());
choose();
ans=min(ans,find_ans());
turn();
ans=min(ans,find_ans());
} int main()
{
n=read(),m=read();
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
a[i][j]=read();
maxn=max(a[i][j],maxn);
minn=min(a[i][j],minn);
}
find_ans2();
printf("%d\n",ans);
return ;
}

本蒟蒻第一篇题解十分不易,希望能帮到大家,谢谢

「JOI 2017 Final」JOIOI 王国的更多相关文章

  1. loj#2334 「JOI 2017 Final」JOIOI 王国

    分析 二分答案 判断左上角是否满足 为了覆盖所有范围 我们依次把右下角,左上角,右上角移动到左上角 代码 #include<bits/stdc++.h> using namespace s ...

  2. LOJ#2764. 「JOI 2013 Final」JOIOI 塔

    题目地址 https://loj.ac/problem/2764 题解 真的想不到二分...不看tag的话... 考虑二分答案转化为判定问题,那么问题就变成了能不能组合出x个JOI/IOI,考虑贪心判 ...

  3. Libre OJ P2332「JOI 2017 Final」焚风现象【差分思想】By cellur925

    题目传送门 这道题开始看起来会很晕...\(qwq\).首先我们要明确题目中的海拔&&温度.温度是受海拔影响的,每次改变的是海拔,我们求的是温度. 我们开始读入的时候便可以处理出开始\ ...

  4. loj 2336「JOI 2017 Final」绳

    loj 首先,所有位置最多被染色一次,因为要染多次的话,还不如一开始就染成最终的颜色.并且你可以一开始就染好色 因为最终长度为2,那么如果染完后这个序列可以被折完,那么首先最多只有两种颜色,还有就是要 ...

  5. loj#2333 「JOI 2017 Final」准高速电车

    分析 我们发现到达一个点一定是先快车再准快车再慢车 于是快车将1-n分为多个区间 每次取出每个区间当前能到达的点的数量 选剩余时间贡献最大的的一个取得贡献并且再能到达的最远点建立准快车 代码 #inc ...

  6. loj#2332 「JOI 2017 Final」焚风现象

    分析 我们发现改变一个区间实际上只有两个端点的贡献变换 代码 #include<bits/stdc++.h> using namespace std; #define int long l ...

  7. 「JOI 2017 Final」绳

    题意 loj 做法 首先我们观察到最后能折起来的充要条件是: 只有两个颜色,除首尾外,所有颜色块内的数量为偶数 因为为偶数,我们进一步推论: 所有颜色块起始位置奇偶性相同 然后因为增与减都会有相同花费 ...

  8. LOJ#2351. 「JOI 2018 Final」毒蛇越狱

    LOJ#2351. 「JOI 2018 Final」毒蛇越狱 https://loj.ac/problem/2351 分析: 首先有\(2^{|?|}\)的暴力非常好做. 观察到\(min(|1|,| ...

  9. 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)

    LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...

随机推荐

  1. bzoj 2242 [SDOI2011]计算器——BSGS模板

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2242 第一道BSGS! 咳咳,我到底改了些什么?…… 感觉和自己的第一版写的差不多……可能是 ...

  2. 12.Selenium+Python案例 -- 今日头条(获取科技栏目的所有新闻标题)

    一:具体代码实现 # -*- coding: utf-8 -*-# @Time : 2018/7/26 16:33# @Author : Nancy# @Email : NancyWangDL@163 ...

  3. 数据格式化和ModelAttribute注解的介绍

    关于数据传递: 客户端传递数据到服务端: 1.使用普通的形式 A.传递简单的数据 如果是说你传递的数据的名称跟控制层中的形参的名称不一致的情况下需要使用 注解: @RequestParam()如果存在 ...

  4. GWT实现平滑移动图片效果

    在一些网站的首页上,顶部总会存在一些平滑移动的图片,一般用来投放广告或者业务介绍.多个图片只在一个区域展示,仅通过一些方法来不停的移动这个区域的图片来达到展示多个图片的目的.如果是普通的网页,使用Jq ...

  5. Java基础--单例类创建和测试

    单例模式的主要作用是保证在Java程序中,某个类只有一个实例存在.单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间:能够避免由于操作多个实例导致 ...

  6. java代码。从键盘输入次数。可控制的

    总结:把一碗水端平,本来水就不多. package com.b; import java.util.Scanner; //想办法用数组.一次性,多个的输出分解质因数 public class fa4 ...

  7. oracle——基础知识(二)未完

    1.select 查询 单独的一条 select 语句 可以一次查询多条记录:但是在 pl/sql 块中,select语句只能 使用INTO子句:必须并且只能返回一行 2.EXECUTE IMMEDI ...

  8. 1.《Spring学习笔记-MVC》系列文章,讲解返回json数据的文章共有3篇,分别为:

    转自:https://www.cnblogs.com/ssslinppp/p/4528892.html [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://w ...

  9. sqlserver 使用维护计划备份

    https://www.cnblogs.com/teafree/p/4240040.html

  10. DAY11-MYSQL数据备份、pymysql模块

    一 IDE工具介绍 生产环境还是推荐使用mysql命令行,但为了方便我们测试,可以使用IDE工具 下载链接:https://pan.baidu.com/s/1bpo5mqj 掌握: #1. 测试+链接 ...