社区讨论
求条
题目总版参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mcmtmrni
- 此快照首次捕获于
- 2025/07/03 11:23 8 个月前
- 此快照最后确认于
- 2025/07/03 11:25 8 个月前
题目如下:
T625457 中位数
题目描述
给定一个大小为 的矩阵 ,你需要从中选择一个大小为 的子矩阵(即选定行区间 与列区间 ,),使得该子矩阵内所有 个元素的“中位数”最小。
定义:令子矩阵内所有元素构成多重集记 。将 中元素按非升序排列为则该子矩阵的中位数定义为 。
求所有可能的 子矩阵的中位数中的最小值。
输入格式
输入格式
第一行包含两个整数 和 ,分别表示矩阵的行/列数和要选取的子矩阵的尺寸,满足 。
接下来的 行,每行包含 个整数,第 行第 列的整数即为 。
输出格式
输出一个整数 ,表示所选 子矩阵中位数的最小可能值。
输入输出样例 #1
输入 #1
CPP3 2
1 7 0
5 8 11
10 4 2
输出 #1
CPP4
输入输出样例 #2
输入 #2
CPP3 3
1 2 3
4 5 6
7 8 9
输出 #2
CPP5
说明/提示
样例 1 解释
所有 子矩阵及其中位数如下:
- 行列区间 :,中位数为第 大的数,即
- 区间 :,中位数
- 区间 :,中位数
- 区间 :,排序后为 ,中位数
因此最小中位数为 。
样例 2 解释
仅有一个 子矩阵,全体元素排序后为 ,中位数为第 大的数 。
数据范围
对于 的数据,。
对于 的数据,,。
我的代码(蒟蒻代码,轻喷 ):
CPP#include<bits/stdc++.h>
using namespace std;
int n,m,a[805][805],l,r,mid,ans,k,maxn=-1;
bool b[805][805];
int s[805][805];
// b 数组用来存元素是否大于 x
// s 数组是 b 的二维前缀和数组
bool check(int x)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(a[i][j]>x)
b[i][j]=1; // 生成 b 数组
else
b[i][j]=0;
//cout<<b[i][j]<<' ';
}
//cout<<endl;
}
//cout<<endl;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
s[i][j]=b[i][j]+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
// 生成 s 数组
//cout<<s[i][j]<<' ';
}
//cout<<endl;
}
//cout<<endl;
for(int i=1;i<=n-m+1;i++)
{
for(int j=1;j<=n-m+1;j++)
{
int sum=s[i+m-1][j+m-1]-s[i][j+m-1]-s[i+m-1][j]+s[i][j];
//cout<<sum<<' ';
if(sum<k)
return true;
// 如果子矩阵中大于 x 的元素数量小于 k,说明这个子矩阵的中位数一定小于等于 x
}
//cout<<endl;
}
//cout<<endl;
return false;
}
int main()
{
cin>>n>>m;
k=m*m/2+1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
maxn=max(maxn,a[i][j]);
}
l=1,r=maxn;
while(l<r) // 二分答案
{
mid=(l+r)>>1;
memset(b,0,sizeof(b));
memset(s,0,sizeof(s));
if(check(mid))
{
r=mid;
ans=mid;
}
else
l=mid+1;
}
cout<<ans;
return 0;
}
程序一直输出 ,求条 qwp
回复
共 0 条回复,欢迎继续交流。
正在加载回复...