Description:
有一个 n ⋅ m n\cdot m n⋅m的矩阵,每个格子中的数用 1 1 1~ n ⋅ m n\cdot m n⋅m之间不同的数表示,求在一个 h ⋅ w h \cdot w h⋅w的字矩阵中的中位数最小,保证 h ⋅ w h \cdot w h⋅w为奇数。
n , m ≤ 1000 n,m\le 1000 n,m≤1000
Solution:
Code:
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i=i##_end_;--i)
#define ll long long
templateinline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templateinline bool chkmax(T &x,T y){return xinline void Rd(T &x){
x=0;char c;
while((c=getchar())<48);
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
}
const int N=1002;
int n,m,h,w,Mid;
int A[N][N];
struct p30{
int tmp[N],tot;
void solve(){
int ans=0x3f3f3f3f;
REP(x1,1,n-h+1) REP(y1,1,m-w+1){
tot=0;
SREP(x2,x1,x1+h) SREP(y2,y1,y1+w) tmp[++tot]=A[x2][y2];
sort(tmp+1,tmp+1+tot);
chkmin(ans,tmp[Mid]);
}
printf("%d\n",ans);
}
}p1;
struct p100{
int sum[N][N];
int Sum(int x1,int y1,int x2,int y2){
return sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]+sum[x1-1][y1-1];
}
bool check(int k){
memset(sum,0,sizeof(sum));
REP(i,1,n) REP(j,1,m) sum[i][j]=(A[i][j]<=k)+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
REP(i,1,n-h+1) REP(j,1,m-w+1) if(Sum(i,j,i+h-1,j+w-1)>=Mid) return 1;
return 0;
}
void solve(){
int L=1,R=n*m,ans=0;
while(L<=R){
int mid=(L+R)>>1;
if(check(mid)) ans=mid,R=mid-1;
else L=mid+1;
}
printf("%d\n",ans);
}
}p2;
int main(){
// freopen("quality.in","r",stdin);
// freopen("quality.out","w",stdout);
Rd(n),Rd(m),Rd(h),Rd(w);
Mid=(h*w)/2+1;
REP(i,1,n) REP(j,1,m) Rd(A[i][j]);
if(n<=30 && m<=30)p1.solve();
else p2.solve();
return 0;
}