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直接缩减元素

 

代码调不出来了。

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 2005
 6 #define ll long long
 7 using namespace std;
 8 int n,m,l[N][N],a[N][N],r[N][N],h[N][N];ll sum[N][N];
 9 ll calc(int x1,int y1,int x2,int y2)
10 {return sum[x2][y2]+sum[x1-1][y1-1]-sum[x1-1][y2]-sum[x2][y1-1];}
11 void print(int x1,int y1,int x2,int y2){
12     if(calc(x1,y1,x2,y2)>2*m){
13         if(x1==x2)y2--;
14         else if(calc(x1+1,y1,x2,y2)>=m)x1++;
15         else x2--; 
16     }
17     printf("%d %d %d %d\n",y1,x1,y2,x2);
18     exit(0);
19 }
20 
21 int main(){
22     //freopen("/home/noilinux/Desktop/data.in","r",stdin);
23     //freopen("/home/noilinux/Desktop/wa.out","w",stdout);
24     scanf("%d%d",&m,&n);
25     for(int i=1;i<=n;i++)
26     for(int j=1;j<=n;j++){
27         scanf("%d",&a[i][j]);
28         sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
29         if(a[i][j]>=m&&a[i][j]<=m*2){
30             printf("%d %d %d %d\n",j,i,j,i);
31             return 0;        
32         }
33     }
34     for(int i=1;i<=n;i++)
35     for(int j=1;j<=n;j++)
36     if(a[i][j]<m)l[i][j]=l[i][j-1]+1;
37     else l[i][j]=0;
38     for(int i=1;i<=n;i++)
39     for(int j=n;j>=1;j--)
40     if(a[i][j]<m)r[i][j]=r[i][j+1]+1;
41     else r[i][j]=0;
42     for(int i=1;i<=n;i++)
43     for(int j=1;j<=n;j++)
44     if(a[i][j]<m)h[i][j]=h[i-1][j]+1;
45     else h[i][j]=0;
46 
47     for(int i=1;i<=n;i++)
48     for(int j=1;j<=n;j++){
49         if(a[i][j]>2*m)continue;
50         if(h[i][j]>1){
51             l[i][j]=min(l[i-1][j],l[i][j]);
52             r[i][j]=min(r[i-1][j],r[i][j]); 
53         }
54         int x1=i-h[i][j]+1,x2=i;
55         int y1=j-l[i][j]+1,y2=j+r[i][j]-1;
56         if(calc(x1,y1,x2,y2)>=m)print(x1,y1,x2,y2);
57     }
58     puts("NIE");
59 }

 

 

 

posted @ 2017-12-25 12:50  _wsy  阅读(305)  评论(0编辑  收藏  举报