【题意】将n*m矩阵分成两个区域,要求满足一定条件,求两区域内部极差较大值最小。n,m<=2000

【算法】二分

【题解】极差的数值满足单调性,所以考虑二分极差。

对于给定的极差,将所有数值排序后,1~a[n*m]-num-1必须选择A,a[1]+num+1~n*m必须选择B,其它不要求。(开始的时候想二分图染色,后来发现排序一下规律就十分明显了)

现在问题转化为矩阵中已知一些格子选A,一些格子选B,求能否组成合法方案。

观察要求满足的条件,很容易得出结论:分界线必须单调,所以就有上A下B或上B下A,递增或递减,组合成四种情况。

针对上B下A,递增的情况(其他情况类似),对于每一列,找到最下面的B和最上面的A,维护A的递增同时看B是否严格在A上方。

复杂度O(n*m log max(Ai))。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int read(){
char c;int s=,t=;
while(!isdigit(c=getchar()))if(c=='-')t=-;
do{s=s*+c-'';}while(isdigit(c=getchar()));
return s*t;
}
int min(int a,int b){return a<b?a:b;}
int max(int a,int b){return a<b?b:a;}
int abs(int x){return x>?x:-x;}
void mins(int &a,int b){if(a>b)a=b;}
void maxs(int &a,int b){if(a<b)a=b;}
//void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
/*------------------------------------------------------------*/
const int inf=0x3f3f3f3f,maxn=; int n,m,A,B,tot,a[maxn*maxn],c[maxn*maxn],minA[maxn],minB[maxn],maxA[maxn],maxB[maxn];
struct cyc{int id,num;}b[maxn*maxn];
bool cmp(cyc a,cyc b){return a.num<b.num;}
int find(int x,int y){
int id=c[(x-)*m+y];
if(id<A)return ;
if(A<=id&&id<B)return ;
return ;
}
bool check(int number)
{
bool ok=;int num;
A=lower_bound(a+,a+tot+,a[tot]-number)-a;
B=upper_bound(a+,a+tot+,a[]+number)-a;
if(A>B)return ;
memset(maxA,0x3f,sizeof(maxA));memset(maxB,0x3f,sizeof(maxB));
memset(minA,,sizeof(minA));memset(minB,,sizeof(minB));
for(int i=;i<=m;i++){
for(int j=;j<=n;j++){
if(find(j,i)==&&maxA[i]==inf)maxA[i]=j;
if(find(j,i)==&&maxB[i]==inf)maxB[i]=j;
if(maxA[i]!=inf&&maxB[i]!=inf)break;
}
for(int j=n;j>=;j--){
if(find(j,i)==&&!minA[i])minA[i]=j;
if(find(j,i)==&&!minB[i])minB[i]=j;
if(minA[i]&&minB[i])break;
}
}
num=n+;ok=;
for(int i=;i<=m;i++){
num=min(num,maxA[i]);
if(minB[i]>=num){ok=;break;}
}
if(ok)return ; num=n+;ok=;
for(int i=;i<=m;i++){
num=min(num,maxB[i]);
if(minA[i]>=num){ok=;break;}
}
if(ok)return ; num=n+;ok=;
for(int i=m;i>=;i--){
num=min(num,maxA[i]);
if(minB[i]>=num){ok=;break;}
}
if(ok)return ; num=n+;ok=;
for(int i=m;i>=;i--){
num=min(num,maxB[i]);
if(minA[i]>=num){ok=;break;}//
}
if(ok)return ; return ;
}
int main()
{
n=read();m=read();
int l=,r=,mid;
for(int i=;i<=n;i++)for(int j=;j<=m;j++){
int num=read();r=max(r,num);
b[++tot]=(cyc){(i-)*m+j,num};
}
sort(b+,b+tot+,cmp);
for(int i=;i<=tot;i++)c[b[i].id]=i;
for(int i=;i<=tot;i++)a[i]=b[i].num;
while(l<r)
{
mid=(l+r)>>;
if(check(mid))r=mid;else l=mid+;
}
printf("%d",l);
return ;
}

【Luogu】P3933 Chtholly Nota Seniorious的更多相关文章

  1. 洛谷P3933 Chtholly Nota Seniorious 【二分 + 贪心 + 矩阵旋转】

    威廉需要调整圣剑的状态,因此他将瑟尼欧尼斯拆分护符,组成了一个nnn行mmm列的矩阵. 每一个护符都有自己的魔力值.现在为了测试圣剑,你需要将这些护符分成 A,B两部分. 要求如下: 圣剑的所有护符, ...

  2. 【题解】Willem, Chtholly and Seniorious Codeforces 896C ODT

    Prelude ODT这个东西真是太好用了,以后写暴力骗分可以用,写在这里mark一下. 题目链接:ヽ(✿゚▽゚)ノ Solution 先把原题解贴在这里:(ノ*・ω・)ノ 简单地说,因为数据是全部随 ...

  3. 【CF896C】Willem, Chtholly and Seniorious

    ODT模板题,ODT适合随机数据下具有维护区间推平操作的序列维护题目,时间复杂度较为玄学.. 代码如下 #include <bits/stdc++.h> #define pb push_b ...

  4. Chtholly Nota Seniorious

    题目背景 大样例下发链接: https://pan.baidu.com/s/1nuVpRS1 密码: sfxg こんなにも.たくさんの幸せをあの人に分けてもらった だから.きっと 今の.私は 谁が何と ...

  5. noip模拟赛 Chtholly Nota Seniorious

    题目背景 大样例下发链接: https://pan.baidu.com/s/1nuVpRS1 密码: sfxg こんなにも.たくさんの幸せをあの人に分けてもらった だから.きっと 今の.私は 谁が何と ...

  6. 【Luogu】P1613 跑路

    [Luogu]P1613 跑路 一.题目 题目描述 小A的工作不仅繁琐,更有苛刻的规定,要求小A每天早上在6:00之前到达公司,否则这个月工资清零.可是小A偏偏又有赖床的坏毛病.于是为了保住自己的工资 ...

  7. 【Luogu】P3930 SAC E#1 - 一道大水题 Knight

    [题目]洛谷10月月赛R1 提高组 [题意]给定n*n棋盘和<=16个棋子,给几个棋子种类和攻击范围,现我方只有一马,求能否吃王. [算法]状压+BFS [题解]16种棋子中,马不能吃马,直接处 ...

  8. 【Luogu】P3927 SAC E#1 - 一道中档题 Factorial

    [题目]洛谷10月月赛R1 提高组 [题意]求n!在k进制下末尾0的个数,n<=1e18,k<=1e16. [题解]考虑10进制末尾0要考虑2和5,推广到k进制则将k分解质因数. 每个质因 ...

  9. 【Luogu】 P3928 SAC E#1 - 一道简单题 Sequence2

    [题目]洛谷10月月赛R1 提高组 [算法]递推DP+树状数组 [题解]列出DP递推方程,然后用树状数组维护前后缀和. #include<cstdio> #include<cstri ...

随机推荐

  1. Java package和import语句

    Java中的package和import语句 如果你想让其他人访问你的类,你一定要把你写的类放到正确的子目录下. 在Java里,对于位于包中的类是这样管理的: Java编译器把包对应于文件系统的目录管 ...

  2. C++纯虚函数、虚函数、实函数、抽象类,重载、重写、重定义

    首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象.继承.动态绑定.通过数据抽象,可以使类的接口与实现分离,使用继承,可以更容易地定义与其他类相似但不 ...

  3. python 查看趴下来的数据

    #coding=utf-8 import re from lxml import etree import requests def requests_view(response): import w ...

  4. python爬虫从入门到放弃(五)之 正则的基本使用(转)

    什么是正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是 事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符”,这个“规则字符” 来表达对字符的一种过滤逻辑. 正则并不是pyth ...

  5. Java内存分配及垃圾回收机制

    Java内存区域 1.内存区域 jvm运行时数据区域 程序计数器 Java虚拟机栈 本地方法栈 方法区 Java堆 大图 2.概念解释 程序计数器   线程私有的一块很小的内存空间,它是当前线程所执行 ...

  6. Visual Stdio 2015打包安装项目的方法(使用Visual Studio Installer)

    首先在官网下载VS2015的Visual Studio Installer 1.创建安装项目 里面最左侧的框框有三个文件夹 1.“应用程序文件夹”即"Application Folder&q ...

  7. BZOJ1293:[SCOI2009]生日礼物——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1293 https://www.luogu.org/problemnew/show/P2564#sub ...

  8. BZOJ1059:[ZJOI2007]矩阵游戏——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=1059 https://www.luogu.org/problemnew/show/P1129 小Q是 ...

  9. 阿里云遇到的坑:CentOS7防火墙(Firewalld),你关了吗?

    阿里云官方教程: https://help.aliyun.com/knowledge_detail/41317.html 百度参考的牛人教程(推荐): http://www.111cn.net/sys ...

  10. [NOIP 2005] 运输计划

    link 这是一道假的图论 思维难度很低,代码量偏高 就是一道板子+二分 树上差分就AC了 注意卡常即可 二分枚举答案x,为时间长度 将每一个长度大于x的计划链长记录下来(有几个,总需要减少多少长度) ...