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
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
NIE
outputdata2
2 1 4 2
HINT
1<=k<=10^9 每个价格都是不大于2*10^9的非负整数
Source
首先可以特判是否有单个元素满足条件,如果没有就说明元素都是<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 }
If you live in the echo,
your heart never beats as loud.
如果你生活在回声里,
你的心跳声永远不会轰鸣作响。