• 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

    对于所有的权值1le 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 }
  • 相关阅读:
    f2fs源码解析(五) node管理结构梳理
    没有什么好神秘的: wait_on_page_bit
    write_back 浅浅分析
    f2fs解析(六)
    转载软件需求文档标准格式
    转载 如何设计一个优秀的数据库
    转载 MySQL创建表的语句 示例
    equals和==的区别 (Java基础)
    转载 【Linux】Linux中常用操作命令
    windows 注册表
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7707243.html
Copyright © 2020-2023  润新知