bzoj1127: [POI2008]KUP
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
题解:
http://blog.csdn.net/popoqqq/article/details/44625423
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 typedef long long int64; 8 char ch; 9 bool ok; 10 void read(int &x){ 11 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 12 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 13 if (ok) x=-x; 14 } 15 const int maxn=2005; 16 int k,n,a[maxn][maxn],head,tail,last,h[maxn],top,l[maxn],r[maxn]; 17 int64 sum[maxn][maxn]; 18 int64 calc(int x,int y,int xx,int yy){return sum[xx][yy]-sum[xx][y-1]-sum[x-1][yy]+sum[x-1][y-1];} 19 struct Data{ 20 int val,id; 21 }que[maxn],stack[maxn]; 22 void output(int x,int y,int xx,int yy){ 23 while (calc(x,y,xx,yy)>k*2){ 24 if (x==xx) y++; 25 else if (calc(x+1,y,xx,yy)>=k) x++; 26 else xx--; 27 } 28 printf("%d %d %d %d\n",y,x,yy,xx); 29 exit(0); 30 } 31 void work(int x){ 32 /*head=1,tail=0,last=1; 33 for (int i=1;i<=n;i++){ 34 while (head<=tail&&que[tail].val>=h[i]) tail--; 35 que[++tail]=(Data){h[i],i}; 36 while (head<=tail&&que[head].val==0) last=que[head++].id+1; 37 if (head<=tail&&calc(x-que[head].val+1,last,x,i)>=k) output(x-que[head].val+1,last,x,i); 38 }*/ 39 top=0; 40 for (int i=1;i<=n+1;i++){ 41 while (top&&stack[top].val>h[i]) r[stack[top--].id]=i-1; 42 stack[++top]=(Data){h[i],i}; 43 } 44 top=0; 45 for (int i=n;i>=0;i--){ 46 while (top&&stack[top].val>h[i]) l[stack[top--].id]=i+1; 47 stack[++top]=(Data){h[i],i}; 48 } 49 for (int i=1;i<=n;i++) 50 if (h[i]) if (calc(x-h[i]+1,l[i],x,r[i])>=k) output(x-h[i]+1,l[i],x,r[i]); 51 } 52 int main(){ 53 read(k),read(n); 54 for (int i=1;i<=n;i++) for (int j=1;j<=n;j++){ 55 read(a[i][j]),sum[i][j]=sum[i][j-1]+a[i][j]; 56 if (k<=a[i][j]&&a[i][j]<=k*2){printf("%d %d %d %d\n",j,i,j,i);return 0;} 57 } 58 for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) sum[i][j]+=sum[i-1][j]; 59 for (int i=1;i<=n;i++){ 60 for (int j=1;j<=n;j++) h[j]=a[i][j]>k*2?0:h[j]+1; 61 work(i); 62 } 63 puts("NIE"); 64 return 0; 65 }