Chtholly Nota Seniorious

题目背景

大样例下发链接: https://pan.baidu.com/s/1nuVpRS1 密码: sfxg

こんなにも、たくさんの幸せをあの人に分けてもらった

だから、きっと

今の、私は

谁が何と言おうと

世界一、幸せな女の子だ

题目描述

——“假如……我是说假如喔。

万一我再过五天就会死,你能不能对我温柔一点?”

巨大的六号兽五天后将袭击浮游大陆。

无数次计算得到的残酷数据表明,只有圣剑瑟尼欧尼斯的适格精灵——珂朵莉·诺塔·瑟尼欧尼斯(Chtholly Nota Seniorious)开启妖精乡之门,才可以以生命为代价守住浮游岛。

“至少,我也希望自己不用消失,也想让别人记住。我也想留下羁绊啊。”

留给妖精少女珂朵莉的时间似乎已经不多了。

年轻的二等技官,妖精仓库的管理员,世界上最后一个人类——威廉·克梅修,数百年前曾经是一名准勇者,掌握着成为一名勇者所需要的所有知识。

大战在即,调整圣剑的状态成为了一项重要的任务。

瑟尼欧里斯(セニオリス)
圣剑的其中之一,在现存的遗迹兵装中,拥有最强大的力量。
拥有非常特殊的资质,只有极少一部分的人才能使用。
由四十一个护符组成。能将所有事物包含不死者都回归「死亡」。

威廉需要调整圣剑的状态,因此他将瑟尼欧尼斯拆分护符,组成了一个nn行mm列的矩阵。

每一个护符都有自己的魔力值。现在为了测试圣剑,你需要将这些护符分成 A,B两部分。

要求如下:

  1. 圣剑的所有护符,恰好都属于两部分中的一部分。

  2. 每个部分内部的方块之间,可以通过上下左右相互到达,而且每个内部的方块之间互相到达,最多允许拐一次弯。

例如

AAAAA  AAAAA  AAAAA
AABAA  BaAAA  AAABB
ABBBA  BBAAA  AAABB
AABAA  BaAAA  ABBBB
AAAAA  AAAAA  BBBBB

  (1)     (2)     (3)      

其中(1)(2)是不允许的分法,(3)是允许的分法。在(2)中,a属于A区域,这两个a元素之间互相到达,没有办法最多只拐一次弯。

现在要问,所有合法的分法中,A区域的极差与B区域的极差 中间较大的一个的 最小值 是多少?

好心而可爱的在一旁默默观察奈芙莲悄悄地告诉你,极差就是区域内最大值减去最小值。

夜晚的风吹拂着,68号岛上的景色竟与地上的森林无异。转念又想,黄金妖精本身就是与森林之中出现,成长,消亡的神秘存在啊。

时间不早了,早上训练中落败的珂朵莉即将回来了。您要尽快和威廉一起调整好圣剑,千万不能迟哟。

输入输出格式

输入格式:

 

第一行两个自然数n,mn,m

接下来nn行,每行mm个自然数A_{i,j}Ai,j表示权值

 

输出格式:

 

一个整数表示答案。

 

输入输出样例

输入样例#1:
4 4
1 12 6 11
11 4 2 14
10 1 9 20
4 17 13 10
输出样例#1:
11

说明

样例解释

1  12 6        11
11 4  2        14
10 1  9        20
4        17 13 10

分法不唯一,如图是一种合法的分法。左边部分极差12-1=11,右边一块极差20-10=10,所以答案取这两个中较大者11。没有别的分法,可以使答案更小。

数据范围与约定

测试点  n    m    
#1-2 \le 1010 \le 1010
#3-4 1 \le 20002000
#5-7 \le 200200 \le 200200
#8-10 \le 20002000 \le 20002000

对于所有的权值1\le A_{i,j} \le 10^91Ai,j109

我们需要按行扫这个矩阵两遍,第一遍从上往下扫,第二遍从下往上扫。

基于贪心的原则,对于每一行,我们从右往左扫。当遇到这一行第一个(最靠右的一个)满足的格子的时候停止,然后下一行从同一个位置开始往左扫。这样贪心可以保证满足条件的同时给下一行更多的选择。

把左边的部分记为A部分,右边的部分记为B部分,则扫的时候顺便维护下每一部分扫到上一行为止的最大最小值,在扫这行的过程中就判断下最大值减最小值会不会爆……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int a[2001][2001],premax[2001][2001],premin[2001][2001];
 7 int sufmax[2001][2001],sufmin[2001][2001],n,m,ans;
 8 bool check1(int k)
 9 {int i,j;
10     int lim=m,maxa=0,mina=2e9,maxb=0,minb=2e9;
11     for (i=1;i<=n;i++)
12     {
13         int flag=0;
14         for (j=lim;j>=0&&flag==0;j--)
15         {
16             if (max(max(maxa,premax[i][j])-min(mina,premin[i][j]),max(maxb,sufmax[i][j+1])-min(minb,sufmin[i][j+1]))<=k)
17             {
18                 lim=j;
19                 maxa=max(premax[i][j],maxa);
20                 if (j+1<=m)
21                 maxb=max(sufmax[i][j+1],maxb);
22                 mina=min(premin[i][j],mina);
23                 if (j+1<=m)
24                 minb=min(sufmin[i][j+1],minb);
25                 flag=1;
26             }
27         }
28         if (flag==0) return 0;
29     }
30     return 1;
31 }
32 bool check2(int k)
33 {int i,j;
34     int lim=m,maxa=0,mina=2e9,maxb=0,minb=2e9;
35     for (i=n;i>=1;i--)
36     {
37         int flag=0;
38         for (j=lim;j>=0&&flag==0;j--)
39         {
40             if (max(max(maxa,premax[i][j])-min(mina,premin[i][j]),max(maxb,sufmax[i][j+1])-min(minb,sufmin[i][j+1]))<=k)
41             {
42                 lim=j;
43                 maxa=max(premax[i][j],maxa);
44                 if (j+1<=m)
45                 maxb=max(sufmax[i][j+1],maxb);
46                 mina=min(premin[i][j],mina);
47                 if (j+1<=m)
48                 minb=min(sufmin[i][j+1],minb);
49                 flag=1;
50             }
51         }
52         if (flag==0) return 0;
53     }
54     return 1;
55 }
56 int main()
57 {int i,j;
58   cin>>n>>m;
59   for (i=1;i<=n;i++)
60   for (j=1;j<=m;j++)
61   scanf("%d",&a[i][j]);
62   for (i=1;i<=n;i++)
63   {
64       premax[i][1]=premin[i][1]=a[i][1];
65       for (j=2;j<=m;j++)
66       {
67           premax[i][j]=max(premax[i][j-1],a[i][j]);
68           premin[i][j]=min(premin[i][j-1],a[i][j]);
69       }
70       sufmax[i][m]=sufmin[i][m]=a[i][m];
71       for (j=m-1;j>=1;j--)
72       {
73           sufmax[i][j]=max(sufmax[i][j+1],a[i][j]);
74           sufmin[i][j]=min(sufmin[i][j+1],a[i][j]);
75       }
76       sufmin[i][m+1]=premin[i][0]=2e9;
77   }
78       int l=0;int r=1e9;
79       while (l<=r)
80       {
81           int mid=(l+r)/2;
82           if (check1(mid)||check2(mid)) ans=mid,r=mid-1;
83           else l=mid+1;
84       }
85       cout<<ans;
86 }

 

posted @ 2017-10-21 22:41  Z-Y-Y-S  阅读(1718)  评论(1编辑  收藏  举报