「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. angular +H5 上传图片 与预览图片

    //index.html <form class="form-horizontal"> <div class="panel panel-default& ...

  2. 洛谷【AT2827】LIS

    浅谈\(DP\):https://www.cnblogs.com/AKMer/p/10437525.html 题目传送门:https://www.luogu.org/problemnew/show/A ...

  3. 在<img src="..." title="..."> 中使title的内容换行的方法

    在<img src="..." title="...">中要使TITILE的内容换行,不能使用html标签,只能用ASCII码,方法如下: < ...

  4. JAVA中数值的表示

    1.Java中用补码形式表示 2.第一位正负位,1表示负,0表示正. 3.原码:一个数的二进制表示.                  3的原码00000011   -3的 原码 10000011 4 ...

  5. POJ3111(最大化平均值)

    K Best Time Limit: 8000MS   Memory Limit: 65536K Total Submissions: 8458   Accepted: 2163 Case Time ...

  6. Day1--Python基础1--上半部分

    一.第一个python程序 在linux下创建一个文件叫做hello.py,并输入 print "Hello World" 然后执行命令:python hello.py,输出 [r ...

  7. Oracle Flushback 学习测试

    Oracle Flushback 学习测试:三思笔记 Flashback恢复 从9i开始,利用oracle查询的多版本一致的特点,实现从回滚段中读取一定时间内在表中操作的数据,被称为 flashbac ...

  8. PHP函数(五)-回调函数

    回调函数是指调用函数的时候将另一个函数作为参数传递到调用的函数中,而不是传递一个普通的变量作为参数 使用回调函数是为了可以将一段自己定义的功能传到函数内部使用 声明回调函数的方法 变量函数声明 < ...

  9. C# Remoting 简单实现

    此处下载源代码(VS2010编译通过)   http://files.cnblogs.com/files/qqhfeng/%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%E6 ...

  10. C# 连接Mysql 字符串

    Database=XXX;Data Source=XXX;User Id=XXX;Password=XXX;pooling=false;CharSet=utf8;port=3306