1127: [POI2008]KUP

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 317  Solved: 111
[Submit][Status][Discuss]

Description

给一个n*n的地图,每个格子有一个价格,找一个矩形区域,使其价格总和位于[k,2k]

Input

输入k n(n<2000)和一个n*n的地图

Output

输出矩形的左上和右下的列-行坐标或NIE

Sample Input

inputdata1
4 3
1 1 1
1 9 1
1 1 1
inputdata2
8 4
1 2 1 3
25 1 2 1
4 20 3 3
3 30 12 2

Sample Output

outputdata1
NIE
outputdata2
2 1 4 2

HINT

1<=k<=10^9 每个价格都是不大于2*10^9的非负整数

Source

感谢vfleaking提供SPJ

Solution

这个题需要思路....

首先假设有一个一维的区间$[l,r]$,那么假设这个区间中满足$\forall x,x<K$,那么且这个区间的和$>=K$,那么答案肯定存在在这个区间中。

证明:

因为这个区间中满足$\forall x,x<K$,所以区间和每加上一个数,区间和的变化量一定是$<K$的;

所以,并不会存在一个数使得一个子区间(连续的)和加上他得到的新区间和直接从$(-\infty,K]$跳过$[K,2*K]$变成$[2*K,+\infty)$.

所以,只要从这个一维的区间的左/右端开始一一删除,就可以得到满足条件的区间。

但是这里的$N*N$的矩阵,所以要利用这个结论就必须扩展到多维区间块上面,但是这个结论是可以拓展的。

这样就是一个子矩阵满足$\forall x,x<K$,且子矩阵和$>=K$,那么这个子矩阵中存在答案。

证明类比上面的证明,这里分类讨论一下,可以利用上面的方法,先一行一行的删除,删成满足条件的,或者只剩一行,转成上述,再一个一个删.

然后就是找出这些需要搞得子矩形的方法了,把$x>2*K$的点认为是障碍,做一遍悬线法,就可以得到所有的极大子矩形,然后一一判断。

当然一开始读入的时候,如果存在一个$1*1$的位置$x$直接满足$x \in [K,2*K]$那么可以直接输出。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define LL long long
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
int K,N,l[][],r[][],h[][];
LL sum[][],a[][];
inline LL Sum(int x1,int y1,int x2,int y2) {return sum[x2][y2]+sum[x1-][y1-]-sum[x2][y1-]-sum[x1-][y2];}
inline void Cut(int x1,int y1,int x2,int y2)
{
while (Sum(x1,y1,x2,y2)>*K)
{
if (x1==x2) {y2--; continue;}
if (Sum(x1,y1,x2-,y2)>=K) {x2--; continue;}
if (Sum(x1+,y1,x2,y2)>=K) {x1++; continue;}
}
printf("%d %d %d %d\n",y1,x1,y2,x2);
exit();
}
int main()
{
K=read(),N=read();
for (int i=; i<=N; i++)
for (int j=; j<=N; j++)
a[i][j]=read(),sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+a[i][j];
for (int i=; i<=N; i++)
for (int j=; j<=N; j++)
if (a[i][j]>=K && a[i][j]<=*K) {printf("%d %d %d %d\n",j,i,j,i); return ;}
for (int i=; i<=N; i++)
{
for (int j=,x=; j<=N; j++)
if (a[i][j]<=*K) l[i][j]=x; else l[i][j]=,x=j;
for (int j=N,x=N+; j>=; j--)
if (a[i][j]<=*K) r[i][j]=x; else r[i][j]=N+,x=j;
}
for (int i=; i<=N+; i++) r[][i]=N+;
for (int i=; i<=N; i++)
for (int j=; j<=N; j++)
if (a[i][j]<=*K)
h[i][j]=h[i-][j]+,
l[i][j]=max(l[i][j]+,l[i-][j]),
r[i][j]=min(r[i][j]-,r[i-][j]); // puts("==========================");
// for (int i=1; i<=N; i++,puts(""))
// for (int j=1; j<=N; j++)
// printf("%d ",h[i][j]);
// puts("==========================");
// for (int i=1; i<=N; i++,puts(""))
// for (int j=1; j<=N; j++)
// printf("%d ",l[i][j]);
// puts("==========================");
// for (int i=1; i<=N; i++,puts(""))
// for (int j=1; j<=N; j++)
// printf("%d ",r[i][j]);
// puts("=========================="); for (int i=; i<=N; i++)
for (int j=; j<=N; j++)
if (a[i][j]<=*K){
// printf("%d %d %d %d\n",i-h[i][j]+1,l[i][j],i,r[i][j]);
if (Sum(i-h[i][j]+,l[i][j],i,r[i][j])>=K) Cut(i-h[i][j]+,l[i][j],i,r[i][j]);
}
puts("NIE");
return ;
}
/*
2 3
3 25 7
6 1 2
16 11 20
*/

【BZOJ-1127】KUP 悬线法 + 贪心的更多相关文章

  1. bzoj1127[POI2008]KUP 悬线法

    Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 485  Solved: 174[Submit][Status][D ...

  2. BZOJ 1057: [ZJOI2007]棋盘制作( dp + 悬线法 )

    对于第一问, 简单的dp. f(i, j)表示以(i, j)为左上角的最大正方形, f(i, j) = min( f(i + 1, j), f(i, j + 1), f(i + 1, j + 1)) ...

  3. BZOJ 3039: 玉蟾宫( 悬线法 )

    最大子矩阵...悬线法..时间复杂度O(nm) 悬线法就是记录一个H向上延伸的最大长度(悬线), L, R向左向右延伸的最大长度, 然后通过递推来得到. ----------------------- ...

  4. 悬线法 || BZOJ 1057: [ZJOI2007]棋盘制作 || Luogu P1169 [ZJOI2007]棋盘制作

    题面:P1169 [ZJOI2007]棋盘制作 题解: 基本是悬线法板子,只是建图判断时有一点点不同. 代码: #include<cstdio> #include<cstring&g ...

  5. 【BZOJ】1057 [ZJOI2007]棋盘制作(悬线法)

    题目 传送门:QWQ 分析 先把题目给出的矩阵变换一下,如果$ a[i][j] $中$ i+j \mod 2 = 1 $那么就对$ a[i][j] $取一下反. 接着就是求原图中最大的0.1子矩阵 详 ...

  6. 【BZOJ】3039: 玉蟾宫 悬线法

    [题意]给定01矩阵,求最大全1子矩阵.n,m<=1000. [算法]动态规划(悬线法) [题解]★对于01矩阵中的任意一个全1极大子矩阵,都可以在其上边界遇到的障碍点处悬线到下边界的点x,则点 ...

  7. BZOJ 1057: [ZJOI2007]棋盘制作 悬线法求最大子矩阵+dp

    1057: [ZJOI2007]棋盘制作 Description 国际象棋是世界上最古老的博弈游戏之一,和中国的围棋.象棋以及日本的将棋同享盛名.据说国际象棋起源于易经的思想,棋盘是一个8*8大小的黑 ...

  8. bzoj 1127 KUP —— 最大子矩形+答案构造

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1127 首先,把权值 > 2*k 的点作为“坏点”,然后在图中用悬线法找权值最大的子矩形 ...

  9. 【BZOJ-3039&1057】玉蟾宫&棋盘制作 悬线法

    3039: 玉蟾宫 Time Limit: 2 Sec  Memory Limit: 128 MBSubmit: 753  Solved: 444[Submit][Status][Discuss] D ...

随机推荐

  1. 每天一个设计模式-4 单例模式(Singleton)

    每天一个设计模式-4 单例模式(Singleton) 1.实际生活的例子 有一天,你的自行车的某个螺丝钉松了,修车铺离你家比较远,而附近的五金店有卖扳手:因此,你决定去五金店买一个扳手,自己把螺丝钉固 ...

  2. 如何判断一个DOM元素正在动画,一个CSS“阻塞”JS的例子

    一般情况下CSS不会直接影响JS的程序逻辑,但是以CSS实现动画的话,这个便不太确定了,这个故事发生在与UED迁移全局样式的过程. 曾经我有一段实现弹出层隐藏动画的代码是这个样子的: if (this ...

  3. iOS 报错汇总

    1. Unknown type name 'class'; did you mean 'Class' 问题解决方法 objectice-c 工程中的类(比如 类 A)使用 C++ 文件时  A.m 文 ...

  4. 简单好记的Jdk 环境变量配置

  5. "Becoming Functional" 阅读笔记+思维导图

    <Becoming Functional>是O'Reilly公司今年(2014)7月发布的一本薄薄的小册子,151页,介绍了函数式编程的基本概念.全书使用代码范例都是基于JVM的编程语言, ...

  6. Unix&Linux技术文章目录(2015-12-22更新)

    Unix & Linux 方面的博客整理.归纳分类,要坚持不懈的学习Unix &Linux,加油!技术需要累积和沉淀.更需要锲而不舍的精神.持之以恒的毅力!借此下面名句勉励自己! 书上 ...

  7. Oracle读取excel

    --解析excel,转换成table,可供查询,支持xls.xlsx --首先修改这个Type,长度改为4000. CREATE OR REPLACE TYPE XYG_PUB_DATA_UPLOAD ...

  8. Oracle计算两个时间戳相差秒数,精确到毫秒

    with t as (select to_timestamp('2015-01-01 11:13:15.023456', 'yyyy-mm-dd hh24:mi:ss.ff9') t1, to_tim ...

  9. python-基本数据类型

    /int整数/ 如: 18.73.84 每一个整数都具备如下功能: class int(object): """ int(x=0) -> int or long i ...

  10. java中可定制的序列化过程 writeObject与readObject

    来源于:[http://bluepopopo.iteye.com/blog/486548] 什么是writeObject 和readObject?可定制的序列化过程 这篇文章很直接,简单易懂.尝试着翻 ...