bzoj1127[POI2008]KUP 悬线法

Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special Judge
Submit: 485  Solved: 174
[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

首先可以特判是否有单个元素满足条件,如果没有就说明元素都是<k或>2k的

>2k的肯定不能选,对于<k的元素,我们将其染色为1    >2k染色为0

现在要做的就是找到颜色全为1的极大子矩阵,判断它其中是否有满足条件的矩阵

如果一个矩阵>=k那么它一定会有一个子矩阵满足条件,可以证明:

如果整个矩阵和<=2k直接输出,剩下的情况都是矩阵和>2k,一直缩小矩阵直到矩阵和<=2k

假设去掉第一行后,矩阵权值和>=k ,去掉第一行继续处理矩阵

假设去掉第一行后,矩阵权值和<k  那么由于矩阵和>2k,第一行肯定是>k的,直接处理第一行

当只有一行时还>2k直接缩减元素

代码调不出来了。

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 2005
#define ll long long
using namespace std;
int n,m,l[N][N],a[N][N],r[N][N],h[N][N];ll sum[N][N];
ll calc(int x1,int y1,int x2,int y2)
{return sum[x2][y2]+sum[x1-][y1-]-sum[x1-][y2]-sum[x2][y1-];}
void print(int x1,int y1,int x2,int y2){
if(calc(x1,y1,x2,y2)>*m){
if(x1==x2)y2--;
else if(calc(x1+,y1,x2,y2)>=m)x1++;
else x2--;
}
printf("%d %d %d %d\n",y1,x1,y2,x2);
exit();
} int main(){
//freopen("/home/noilinux/Desktop/data.in","r",stdin);
//freopen("/home/noilinux/Desktop/wa.out","w",stdout);
scanf("%d%d",&m,&n);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
scanf("%d",&a[i][j]);
sum[i][j]=sum[i-][j]+sum[i][j-]-sum[i-][j-]+a[i][j];
if(a[i][j]>=m&&a[i][j]<=m*){
printf("%d %d %d %d\n",j,i,j,i);
return ;
}
}
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(a[i][j]<m)l[i][j]=l[i][j-]+;
else l[i][j]=;
for(int i=;i<=n;i++)
for(int j=n;j>=;j--)
if(a[i][j]<m)r[i][j]=r[i][j+]+;
else r[i][j]=;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(a[i][j]<m)h[i][j]=h[i-][j]+;
else h[i][j]=; for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
if(a[i][j]>*m)continue;
if(h[i][j]>){
l[i][j]=min(l[i-][j],l[i][j]);
r[i][j]=min(r[i-][j],r[i][j]);
}
int x1=i-h[i][j]+,x2=i;
int y1=j-l[i][j]+,y2=j+r[i][j]-;
if(calc(x1,y1,x2,y2)>=m)print(x1,y1,x2,y2);
}
puts("NIE");
}
上一篇:Java 中常用缓存Cache机制的实现


下一篇:CSS3 用户界面