题意:
给出一个矩阵,求这个矩阵中权值和第k小的长在xmin到n之间,宽在ymin到m之间的子矩阵。n,m≤1000,k≤250000。
题解:
首先求出长为xmin,宽为ymin的子矩阵放入优先队列,每次取出时如果该矩阵之前没有出现过(用set判重),则将其扩展并放入优先队列,输出第k个不重复的(这里指位置不重复的,权值可以相等)。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 #include <set> 6 #define inc(i,j,k) for(int i=j;i<=k;i++) 7 #define maxn 1010 8 using namespace std; 9 10 inline int read(){ 11 char ch=getchar(); int f=1,x=0; 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} 13 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 14 return f*x; 15 } 16 int sum[maxn][maxn],n,m,xmin,ymin,k,tot; 17 struct nd{ 18 int x,y,l,c,v; 19 bool operator < (const nd &a)const{ 20 if(v!=a.v)return v>a.v; if(x!=a.x)return x<a.x; if(y!=a.y)return y<a.y; 21 if(l!=a.l)return l<a.l; return c<a.c; 22 }; 23 }; 24 priority_queue<nd>q; set<nd>st; 25 int main(){ 26 n=read(); m=read(); xmin=read(); ymin=read(); k=read(); 27 inc(i,1,n)inc(j,1,m){int x=read(); sum[i][j]=sum[i-1][j]-sum[i-1][j-1]+sum[i][j-1]+x;} 28 inc(i,1,n-xmin+1)inc(j,1,m-ymin+1){ 29 q.push((nd){i,j,xmin,ymin,sum[i+xmin-1][j+ymin-1]-sum[i+xmin-1][j-1]-sum[i-1][j+ymin-1]+sum[i-1][j-1]}); 30 } 31 while(!q.empty()){ 32 nd x=q.top(); q.pop(); if(st.find(x)!=st.end())continue; 33 tot++; if(tot==k){printf("%d",x.v+1); break;} st.insert(x); 34 if(x.x+x.l<=n) 35 q.push((nd){x.x,x.y,x.l+1,x.c,sum[x.x+x.l][x.y+x.c-1]-sum[x.x+x.l][x.y-1]-sum[x.x-1][x.y+x.c-1]+sum[x.x-1][x.y-1]}); 36 if(x.y+x.c<=m) 37 q.push((nd){x.x,x.y,x.l,x.c+1,sum[x.x+x.l-1][x.y+x.c]-sum[x.x+x.l-1][x.y-1]-sum[x.x-1][x.y+x.c]+sum[x.x-1][x.y-1]}); 38 if(x.x+x.l<=n&&x.y+x.c<=m) 39 q.push((nd){x.x,x.y,x.l+1,x.c+1,sum[x.x+x.l][x.y+x.c]-sum[x.x+x.l][x.y-1]-sum[x.x-1][x.y+x.c]+sum[x.x-1][x.y-1]}); 40 } 41 return 0; 42 }
20161110